搜索电影小demo-react版(10.5-10.6)
通过这个小例子学习了react的哪些知识?
1. 钩子 useState 相当于state和setState ,写法 const [searchValue, setSearchValue] = useState(""),
2. 钩子 useReducer, 在 hooks 中提供了的 useReducer 功能,可以增强 ReducerDemo 函数提供类似 Redux 的功能,引入 useReducer 后,useReducer 接受一个 reducer 函数作为参数,reducer 接受两个参数一个是 state 另一个是 action 。然后返回一个状态 count 和 dispath,count 是返回状态中的值,而 dispatch 是一个可以发布事件来更新 state 的。
3. 钩子 useEffect 使用useEffect
,可以直接在函数组件内处理生命周期事件。 如果你熟悉 React class 的生命周期函数,你可以把 useEffect
Hook 看做 componentDidMount
,componentDidUpdate
和 componentWillUnmount
这三个函数的组合
4. 例子用组件可以拆分为头部组件/搜索组件/电影组件
其中头部组件只需要接收demo的标题
1 2 3 4 5 6 7 8 9 | import React from 'react' const Header = (props) => { return ( <header className= "App-header" > <h2>{props.text}</h2> </header> ) } export default Header |
其中搜索组件需要做的事情(由一个搜索框和按钮组成),用到了useState钩子作用是重置或输入框改变时改变state里的值,还有向父组件传事件时会用到props,如点击了搜索props.search(searchValue),searchValue取的就是state里的值, 包住方法用{},input的值value就可以,需要用form表单来包住具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import React, { useState } from "react" ; const Search = (props) => { const [searchValue, setSearchValue] = useState( "" ) // 当输入框改变时调用 const handleSearchInputsChange = (e) => { setSearchValue(e.target.value); } // 重置 const resetInputField = () => { setSearchValue( "" ); } const callSearchFunction = (e) => { e.preventDefault(); // 阻止事件的默认点击事件执行 props.search(searchValue); resetInputField(); } return ( <form className= "search" > <input value={searchValue} onChange={handleSearchInputsChange} type= "text" ></input> <input onClick={callSearchFunction} type= "submit" value= "SEARCH" ></input> </form> ) } export default Search |
其中电影组件需要做的事情,设置无网时或者说是默认图片,设置电影名字和介绍等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import React from "react" ; const DEFAULT_PLACEHOLDER_IMAGE = "https://m.media-amazon.com/images/M/MV5BMTczNTI2ODUwOF5BMl5BanBnXkFtZTcwMTU0NTIzMw@@._V1_SX300.jpg" ; const Movie = ({ movie }) => { const poster = movie.Poster === "N/A" ? DEFAULT_PLACEHOLDER_IMAGE : movie.Poster; return ( <div className= "movie" > <h2>{movie.Title}</h2> <div> <img width= "200" alt={`The movie titled: ${movie.Title}`} src={poster} /> </div> <p>({movie.Year})</p> </div> ); }; export default Movie; |
app.js需要把上面三个组件集成起来,react原生是支持fetch请求的,加载电影资源时分为三种情况,请求时/请求成功/请求失败
请求时,需要加载loading/请求成功需要给电影子组件传递电影数据,loading消失/请求失败loading消息,提示错误消息,具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | import Header from './Header' ; import Search from './Search' import Movie from './Movie' import './App.css' ; import React, { useReducer, useEffect } from 'react' ; // 电影api const MOVIE_API_URL = "https://www.omdbapi.com/?s=man&apikey=4a3b711b" ; const initialState = { loading: true , movies: [], errorMessage: null } // 三个状态 SEARCH_MOVIES_REQUEST/SEARCH_MOVIES_SUCCESS/SEARCH_MOVIES_FAILURE const reducer = (state, action) => { switch (action.type) { case 'SEARCH_MOVIES_REQUEST' : return { ...state, loading: true , errorMessage: null } case 'SEARCH_MOVIES_SUCCESS' : return { ...state, loading: false , movies: action.playload } case 'SEARCH_MOVIES_FAILURE' : return { ...state, loading: false , errorMessage: action.error } default : return state; } } // 无关键字或错误数据 {"Response":"False","Error":"Incorrect IMDb ID."} const App = () => { // 设置state状态 // const [loading, setLoading] = useState(true) // const [movies, setMovies] = useState([]) // const [errorMessage, setErrorMessage] = useState(null) // useEffect(() => { // fetch(MOVIE_API_URL) // .then(response => response.json()) // .then(jsonResPonse => { // setLoading(false); // setMovies(jsonResPonse.Search); // }) // }, []) // const search = searchValue => { // setLoading(true); // setErrorMessage(null); // fetch(`https://www.omdbapi.com/?s=${searchValue}&apikey=4a3b711b`) // .then(response => response.json()) // .then(jsonResponse => { // if (jsonResponse.Response === 'True') { // setLoading(false); // setMovies(jsonResponse.Search); // } else { // setLoading(false); // setErrorMessage(jsonResponse.Error); // } // }) // } // 用useReducer替换useState const [state, dispatch] = useReducer(reducer, initialState); useEffect(() => { fetch(MOVIE_API_URL) .then(response => response.json()) .then(jsonResPonse => { dispatch({ type: 'SEARCH_MOVIES_SUCCESS' , playload: jsonResPonse.Search }) }) }, []) const search = searchValue => { dispatch({ type: "SEARCH_MOVIES_REQUEST" }); // setLoading(true); // setErrorMessage(null); fetch(`https: //www.omdbapi.com/?s=${searchValue}&apikey=4a3b711b`) .then(response => response.json()) .then(jsonResponse => { if (jsonResponse.Response === 'True' ) { // setLoading(false); // setMovies(jsonResponse.Search); dispatch({ type: 'SEARCH_MOVIES_SUCCESS' , playload: jsonResponse.Search }); } else { // setLoading(false); // setErrorMessage(jsonResponse.Error); dispatch({ type: 'SEARCH_MOVIES_FAILURE' , errorMessage: jsonResponse.Error }); } }) } const { movies, loading, errorMessage } = state; return ( <div className= "App" > <Header text= "HOOKED" /> <Search search={search}/> <p className= "App-intro" >Sharing a few of our favourite movies</p> <div className= "movies" > { loading && !errorMessage ? (<span>...loading</span>) : errorMessage ? (<div className= "errorMessage" >{errorMessage}</div>) : (movies.map((movie, index) => ( <Movie key={`${index}-${movie.title}`} movie={movie}/> ))) } </div> </div> ); } export default App; |
最后详细教程介绍请参考下面的网站
参考网站链接: https://www.freecodecamp.org/news/how-to-build-a-movie-search-app-using-react-hooks-24eb72ddfaf7/
将来的自己,会感谢现在不放弃的自己!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现