daily-share icon indicating copy to clipboard operation
daily-share copied to clipboard

useReducer 和 React.createContext 结合 处理一些多级组件传值 (2020-09-05)

Open yaogengzhu opened this issue 4 years ago • 0 comments

背景: 在实际的开发过程中,我们可能像自组件共享一些props., 但是传递过深的话,需要多次写props ,子组件接受! 写起来非常麻烦! 如果使用以下方式,过程就变得简单起来。

import React, { useContext, useReducer } from 'react'

const Son = () => {
    const  { name, price ,stock } = useContext(MyContext)
    return(
        <div style={{ color: 'blue'}}>
            <p>这个是子组件的子组件</p>
            <ul>
                <li>{name}</li>
                <li>{price}</li>
                <li>{stock}</li>
            </ul>
        </div>
    )
}

const Count = () => {
    const { name, price ,stock } = useContext(MyContext)
    return (
        <div>
            <div style={{ color: 'red'}}>
                <span>这个是子组件</span>
                <ul>
                    <li>{name}</li>
                    <li>{price}</li>
                    <li>{stock}</li>
                </ul>
            </div>
            <Son />
        </div>
    )
}

/**
 * 接口定义
 */
interface IGoodsInfo {
    name: string
    price: number
    stock: number
}
enum IGoodsAction{
    set
}

const IGoodsInfo: IGoodsInfo = {
    name: '香菇',
    price: 12,
    stock: 100
}

export const goodsReducer = (state: IGoodsInfo, action: {
    type: IGoodsAction,
    value: IGoodsInfo 
}): IGoodsInfo => {
    switch(action.type) {
        case IGoodsAction.set :
            return action.value
    }
}

// :创建一个上下文的容器(组件), defaultValue可以设置共享的默认数据
/**
 * 不理解 createContext 可以参考这篇文章:https://www.jianshu.com/p/65b348bf86ad
 */
const MyContext = React.createContext(IGoodsInfo)
const Page3 = () => {
    // 使用useReducer 
    /**
     *  不理解useReducer 可以参考这篇文章:https://www.jianshu.com/p/14e429e29798
     */
    const [sate, dispatch] = useReducer(goodsReducer, IGoodsInfo)
    return (
        <div>
           <div style={{ color: 'deepPink'}}>
               <p>我是父组件</p>
               <ul>
                   <li>{ sate.name }</li>
                   <li> { sate.price } </li>
                   <li>{ sate.stock }</li>
               </ul>
           </div>

           <button onClick={() =>{
               dispatch({
                   type: IGoodsAction.set,
                   value: {
                       ...sate,
                       price: 1000
                   }
               })
           }}>我要在父组件中改变他们</button>
            <MyContext.Provider value={sate}>
                <Count />

            </MyContext.Provider>
        </div>
    )
}
export default Page3

yaogengzhu avatar Sep 05 '20 06:09 yaogengzhu