美文网首页
React Hooks demo

React Hooks demo

作者: Joemoninni | 来源:发表于2020-10-10 16:40 被阅读0次

react hooks demo

  1. 创建所需要的组件,这个项目我们分成三个组件, 分别是头部,搜索框,电影列表

    // Header.js
    import React from 'react'
    export default function Header(props) {
     return (
         <div>
             <header className="app_header">
                 <h2>{props.text}</h2>
                </header>
            </div>
        )    
    }
    
    // Movie.js
    import React from 'react'
    
    const DEFAULT_PLACEHOLDER_IMAGE = 'https://m.media-amazon.com/images/M/MV5BMTczNTI2ODUwOF5BMl5BanBnXkFtZTcwMTU0NTIzMw@@._V1_SX300.jpg'
    
    export default function Movie({movie}) {
        const poster = movie.Poster = 'N/A' ? DEFAULT_PLACEHOLDER_IMAGE : movie.Poster
        return (f
         <div className="movie">
             <h2>{movie.Title}</h2>
                <div>
                 <img width="200" src={poster} alt={`The Movie Titled: ${movie.Title}`} />
                </div> 
            </div>
        )
    }
    
    // Search.js
    import React, { useState } from 'react'
    
    export default function Search(props) {
        const [searchValue, setSearchValue] = useState('')
        
        const handleSearchInputChanges = (e) => {
            setSearchValue(e.target.value)
        }
        const resetInputField = () => {
            setSearchValue('')
        }
        const handleInputSearch = (e) => {
            e.preventDefault()
            props.search(searchValue)
            resetInputField()
        }
        
        return (
         <div>
             <form className="search">
                 <input type="text" onChange={handleSearchInputChanges} value={searchValue}  />
                    <input type="submit" onClick={handleInputSearch} value="SEARCH" />
                </form>
            </div>
        )
    }
    
  2. 创建App.js

    // App.js
    import React, { useState, useEffect } from 'react'
    import Header from './Header.js'
    import Movie from './Movie.js'
    import Search from './Search.js'
    import axios from 'axios'
    
    const MOVIE_API_URL = 'https://www.omdbapi.com/?s=man&apikey=62b53dxx'
    
    export default function App() {
        const [loading, setLoading] = useState(true)
        const [movie, setMovie] = useState([])
        const [errorMessage, setErrorMessage] = useState(null)
        /**
        这里我们使用了三个useState函数,所以在一个组件中可以有多个useState函数
        1. loading: 用于处理加载状态,加载时页面呈现一个Loading
        2. movie: 用于处理从服务器获取的movies数组/数据
        3. errorMessage: 用于处理在发出API请求时可能发生的任何错误
        */
        
        const search = (searchVal) => {
            setLoading(false)
            setErrorMessage(null)
            axios.get(`https://www.omdbapi.com/?s=${searchVal}&apikey=62b53dxx`).then(res => {
                if (res.data.Response === 'True') {
                    setMovie(res.data.Search)
                } else {
                    setErrorMessage(res.data.Error)
                }
                setLoading(false)
            })
        }
        
        useEffect(() => {
            axios.get(MOVIE_API_URL).then(res => {
                setMovie(res.data.Search)
                setLoading(false)
            })
        }, [])
        /**
        这里使用了useEffect,这个Hooks可以让你在函数式组件中执行副作用, 所谓的副作用是指数据获取,订阅和手动操作DOM
        我们也可以将useEffect看作是componentDidMount, componentDidUpdate和componentWillUnmount的组合(这是因为在组件第一次render之后(componentDidMount)和每次组件更新之后(componentDidUpdate), useEffect都会被调用)
        */
        
        return (
         <div className="App">
             <Header text={Movies Demo} />
                <Search search={search} />
                <div className="movies">
                    {
                        loading && !errorMessage ? (<span>loading...</span>)   : 
                         errorMessage            ? (<div>{errorMessage}</div>) : 
                        (movie.map((item, index) => {<Movie key={`${index}-${movie.Title}`} movie={item} />}))
                    }
                </div>
            </div>
        )
    }
    

    如果项目中需要定义多个状态,那我们使用useState会显得代码比较冗余,也比较乱,建议用useReducer,统一管理下代码。我们修改App.js文件如下:

    import React, { useReducer } from 'react'
    import Header from './Header'
    import Movie from './Movie'
    import Search from './Search'
    import axios from 'axios'
    
    const initialState = {
        loading: true,
        movie: [],
         errorMessage: null
    }
    
    const reducer = (state, action) => {
        switch(action.type) {
            case 'SEARCH_MOVIE_REQUEST':
                return {
                    ...state,
                    loading: true,
                    errorMessage: null
                } 
            case "SEARCH_MOVIE_SUCCESS":
                return {
                    ...state,
                    loading: false,
                    movie: action.payload
                }
            case 'SEARCH_MOVIE_FAILURE': 
                return {
                    ...state,
                    loading: false,
                    errorMessage: action.error
                }
            default: 
                return state
        }
    }
    
    export default App() {
        const [state, dispatch] = useReducer(reducer, initialState)
        
        const { loading, movie, errorMessage } = state
        
        const search = (searchVal) => {
            // setLoading(false)
            // setErrorMessage(null)
            // 修改为:
            dispatch({
                type: 'SEARCH_MOVIE_REQUEST'
            })
            
            axios.get(`https://www.omdbapi.com/?s=${searchVal}&apikey=62b53dxx`).then(res => {
                if (res.data.Response === 'True') {
                    // setMovie(res.data.Search)
                    // 修改为:
                    dispatch({
                        type: 'SEARCH_MOVIE_SUCCESS',
                        payload: res.data.Search
                    })
                } else {
                    // setErrorMessage(res.data.Error)
                    // 修改为:
                    dispatch({
                        type: 'SEARCH_MOVIE_FAILURE',
                        error: res.data.Error
                    })
                }
                // setLoading(false)
            })
        }
        
        useEffect(() => {
            axios.get(MOVIE_API_URL).then(res => {
                // setMovie(res.data.Search)
                // setLoading(false)
                // 修改为:
                dispatch({
                    type: 'SEARCH_MOVIE_SUCCESS',
                    payload: res.data.Search
                })
            })
        }, [])
        
         return (
         <div className="App">
             <Header text={Movies Demo} />
                <Search search={search} />
                <div className="movies">
                    {
                        loading && !errorMessage ? (<span>loading...</span>)   : 
                         errorMessage            ? (<div>{errorMessage}</div>) : 
                        (movie.map((item, index) => {<Movie key={`${index}-${movie.Title}`} movie={item} />}))
                    }
                </div>
            </div>
        )
    }
    

    这样好像看起来还是代码有点多,而且全部都写在App.js这个文件中, 我们可以把state和reducer拆分到另外的文件,然后再引入

    我们在src目录下新建一个store文件夹,store目录下再建一个reducer文件夹

    //  src/store/reducer/index.js
    
    export const initialState = {
        loading: true,
        movie: [],
        errorMessage: null
    }
    
    export const reducer = (state, action) => {
        switch(action.type) {
                case: 'SEARCH_MOVIE_REQUSET': 
                 return {    
                        ...state, 
                        loading: false,
                        errorMessage: null
                    }
                case: 'SEARCH_MOVIE_SUCCESS':
                 return {
                        ...state, 
                        loading: true,
                        movie: action.payload
                    }
                case: 'SEARCH_MOVIE_FAILURE': 
                 return {
                        ...state, 
                        loading: true,
                        errorMessage: action.error
                    }
            default: 
                return state
        }
    }
    

    App.js中引入,然后就可以使用我们自定义的state和reducer了

    import { initialState, reducer } from '../store/reducer'
    

相关文章

  • React Hooks demo

    react hooks demo 创建所需要的组件,这个项目我们分成三个组件, 分别是头部,搜索框,电影列表// ...

  • 实现简单的React hooks 如 useState, use

    例子:https://codesandbox.io/s/react-hooks-demo-6-5iey8?file...

  • 填坑之路:React状态管理

    文中涉及的React demo代码使用了16.8的新增特性Hooks[https://reactjs.org/do...

  • React Hooks

    React Hooks Hooks其实就是有状态的函数式组件。 React Hooks让React的成本降低了很多...

  • react-hooks

    前置 学习面试视频 总结react hooks react-hooks react-hooks为函数组件提供了一些...

  • React Hooks

    前言 React Conf 2018 上 React 提出了关于 React Hooks 的提案,Hooks 作为...

  • 5分钟简单了解React-Hooks

    首先附上官网正文?:React Hooks Hooks are a new addition in React 1...

  • react-hooks

    react-hooks react-hooks 是react16.8以后,react新增的钩子API,目的是增加代...

  • React-hooks API介绍

    react-hooks HOOKS hooks概念在React Conf 2018被提出来,并将在未来的版本中被...

  • React Hooks 入门

    React Hooks 是 React v16.8 版本引入了全新的 API。 React Hooks 基本概念 ...

网友评论

      本文标题:React Hooks demo

      本文链接:https://www.haomeiwen.com/subject/dbzlpktx.html