React组件传值(用函数组件举例,涉及多种hook)

总结一下React中组件传值。组件分为函数组件和类组件。组件传值分为父子传值和兄弟传值。

一、父子传值

父组件传值给子组件是较为常见的组件传值方式。

function Father(){

    return(
        <div className="c-father" >
            <Son text="theme" />
        </div>
    ) 
}
function Son(props){

    return(
        <div>
            <div className="c-father_son">{props.text}</div>
        </div>
    ) 
}
ReactDOM.render(
    <Father />,
    document.getElementById("test")
)

子组件传值给父组件,需要父组件首先将一个回调函数作为props传给子组件,子组件通过回调函数传值给父组件。

function Father(){
    const [color,setColor] = React.useState(false);
    const changeColor = (isChange)=>{
        setColor(isChange);
    }
    return(
        <div className="c-father" style={{backgroundColor:color?"pink":"yellow"}}>
            <Son text="theme" color={changeColor} />
        </div>
    ) 
}
function Son(props){

    return(
        <div>
            <div className="c-father_son">{props.text}</div>
            <button onClick={()=>{props.color(true)}}>切换颜色</button>
        </div>
    ) 
}
ReactDOM.render(
    <Father />,
    document.getElementById("test")
)

二、兄弟传值

兄弟传值其实和父子传值类似,就是子传父和父传子的结合。父组件作为兄弟组件传值的中介。

function Father(){
    const [color,setColor] = React.useState(false);
    const [text,setText] = React.useState();
    const changeColor = (isChange)=>{
        setColor(isChange);
    }
    const showText = (content)=>{
        setText(content);
    }
    return(
        <div className="c-father" style={{backgroundColor:color?"pink":"yellow"}}>
            <Son text="theme" color={changeColor} showText={showText}/>
            <AnotherSon text={text}/>
        </div>
    ) 
}
function Son(props){

    return(
        <div>
            <div className="c-father_son">{props.text}</div>
            <button onClick={()=>{props.color(true)}}>切换颜色</button>
            <button onClick={()=>{props.showText("我要给兄弟传值")}}>我要传值</button>
        </div>
    ) 
}
function AnotherSon(props){

    return(
        <div>{props.text}</div>
    )
}
ReactDOM.render(
    <Father />,
    document.getElementById("test")
)

三、补充

1.关于父传子,如果目的子组件在组件嵌套的深层,直接用props传值是不实际的,可以考虑用context。

const statusContext = React.createContext("good");
function Father(){
    const [color,setColor] = React.useState(false);
    const [text,setText] = React.useState();
    const changeColor = (isChange)=>{
        setColor(isChange);
    }
    const showText = (content)=>{
        setText(content);
    }

    return(
        <div className="c-father" style={{backgroundColor:color?"pink":"yellow"}}>
            <statusContext.Provider value="nice">
                <Son text="theme" color={changeColor} showText={showText}/>
            </statusContext.Provider>

            {/*<AnotherSon text={text}/>*/}
        </div>
    ) 
}
function Son(props){

    return(
        <div>
            <AnotherSon />
            <div className="c-father_son">{props.text}</div>
            <button onClick={()=>{props.color(true)}}>切换颜色</button>
            <button onClick={()=>{props.showText("我要给兄弟传值")}}>我要传值</button>
        </div>
    ) 
}
function AnotherSon(props){
    const status = React.useContext(statusContext);
    return(
        <div>
            {status}
            <div>{props.text}</div>
        </div>

    )
}


ReactDOM.render(
    <Father />,
    document.getElementById("test")
)

React创建context对象,在目的子组件利用useContext接收context对象,目的子组件会根据离它最近的Provider提供的value值发生变化。

2.关于子组件传值给父组件或者兄弟组件间传值,除了用props+回调函数之外,也可以利用ref解决

const statusContext = React.createContext("good");
function Father(){
    const [color,setColor] = React.useState(false);
    const [text,setText] = React.useState();
    const changeColor = (isChange)=>{
        setColor(isChange);
    }
    const sonRef = React.createRef();
    const handleClick = ()=>{
        sonRef.current.output("今天天气预报");
    }
    return(
        <div className="c-father" style={{backgroundColor:color?"pink":"yellow"}}>
            <statusContext.Provider value="nice">
                <Son text="theme" color={changeColor} clickEve={handleClick}/>
            </statusContext.Provider>

            <AnotherSon ref={sonRef}/>
        </div>
    ) 
}

function Son(props){

    return(
        <div>

            <div className="c-father_son">{props.text}</div>
            <button onClick={()=>{props.color(true)}}>切换颜色</button>
            <button onClick={()=>{props.clickEve()}}>我要传值</button>
        </div>
    ) 
}
const AnotherSon = React.forwardRef((props,ref)=>{
    const [test,setTest] = React.useState("");
    React.useImperativeHandle(ref,()=>({
        output:(warn)=>{
            console.log("this is",warn);
            setTest(warn);
        }
    }))
    //console.log(ref)
    return(
        <div ref={ref}>{test}</div>
    )

})

ReactDOM.render(
    <Father />,
    document.getElementById("test")
)

首先利用forwardRef创建目的子组件,将ref给到具体DOM节点。在父组件创建ref,并给到目的子组件。目的子组件利用useImperativeHandle向父组件暴露自定义属性,父组件创建方法调用目的子组件的属性,并将方法传给作为发送数据的子组件。

除了ref,还有useReducer,这和react的redux有点类似。利用useContext将reducer的state转换为一组共有父组件的子组件的共有变量。

const statusContext = React.createContext("good");
const initState = {count:0};
function reducer(state,action){
    console.log(action.type)
    switch(action.type){
        case "plus":return{count:state.count+1};break;
        case "minus":return{count:state.count-1};break;
        default:throw new Error();
    }
}

function Father(){
    const [text,setText] = React.useState();
    const [state,dispatch] = React.useReducer(reducer,initState);
    const showText = (content)=>{
        setText(content);
    }
    const sonRef = React.createRef();
    const handleClick = ()=>{
        sonRef.current.output("今天天气预报");
    }
    return(
        <div className="c-father" style={{backgroundColor:color?"pink":"yellow"}}>
            <statusContext.Provider value={{count:state.count,dispatch:dispatch}}>
                //将state和dispatch一起分发下去
                <Son text="theme"  showText={showText} clickEve={handleClick}/>
                <AnotherSon text={text} ref={sonRef}/>
            </statusContext.Provider>


        </div>
    ) 
}

function Son(props){
    const {dispatch} = React.useContext(statusContext);

    //console.log(dispatch)
    return(
        <div>

            <div className="c-father_son">{props.text}</div>
            <button onClick={()=>{dispatch({type:"plus"})}}>切换数字</button>
            <button onClick={()=>{props.clickEve()}}>我要传值</button>
        </div>
    ) 
}
const AnotherSon = React.forwardRef((props,ref)=>{
    const [test,setTest] = React.useState("");
    const {count} = React.useContext(statusContext);
    React.useImperativeHandle(ref,()=>({
        output:(warn)=>{
            console.log("this is",warn);
            setTest(warn);
        }
    }))
    console.log(count)
    return(
        <div ref={ref}>{count}</div>
    )

})

ReactDOM.render(
    <Father />,
    document.getElementById("test")
)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值