React Hooks demo

react hooks demo

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

    // Header.js
    import React from 'react'
    export default function Header(props) {
     return (
         

    {props.text}

    ) }
    // 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
         

    {movie.Title}

    {`The
    ) }
    // 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 (
         
    ) }
  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 (
         
    { loading && !errorMessage ? (loading...) : errorMessage ? (
    {errorMessage}
    ) : (movie.map((item, index) => {})) }
    ) }

    如果项目中需要定义多个状态,那我们使用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 (
         
    { loading && !errorMessage ? (loading...) : errorMessage ? (
    {errorMessage}
    ) : (movie.map((item, index) => {})) }
    ) }

    这样好像看起来还是代码有点多,而且全部都写在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)