React父子之间相关控制渲染总结

111 阅读2分钟
  • 前提认知:数据从上向下传递的

  • 怎么实现父组件控制渲染子组件

    • 在父组件控制子组件需要的state值,以props传递
        * 这种方式就是常规的父组件向子组件传参 *
    
        function Parent (){
            return <Child data={'name is parent'}/>
        }
    
        function Child ({data}){
            return <>{data}</>
        }
    
    • 父组件直接绘制子组件需要的DOM,render-props
        * 在父组件绘制子组件UI,可以同时获取子组件和父组件的state相关值 *
    
        function Parent (){
            const [parentData,setParentData] = useState('this is parentData')
    
            return <Child renderItem={(childItemData) => {
                return <div className='childScope'>show:{parentData}{childItemData}</div>
            }}/>
        }
    
        function Child ({renderItem}){
            const [childData,setChildData] = useState('this is childData')
            return <>{renderItem(childData)}</>
        }
    
  • 怎么实现子组件控制渲染父组件

    • 在子组件控制父组件的state值【直接状态设置函数或者回调函数】
        * 这个可以理解父组件向子组件传递了一个函数 - 直接是状态设置函数 *
    
        function Parent (){
            const [parentData,setParentData] = useState(false)
    
            return (<>
                {
                   parentData ? <div>状态为true,需要显示父级</div> : null
                }
                <Child setParentData={setParentData} />
            </>)
        }
    
        function Child ({setParentData}){
            function handleClick(){
                setParentData(true)
            }
    
            return <div onClick={handleClick}>{'this is childData'}</div>
        }
    
        * 这个可以理解父组件向子组件传递了一个函数 - 回调函数形式处理 *
    
        function Parent (){
            const [parentData,setParentData] = useState(false)
            function handleOnChildCallback(){
                setParentData(true)
            }
    
            return (<>
                {
                    parentData ? <div>状态为true,需要显示父级</div> : null
                }
                <Child onChildCallback={handleOnChildCallback} />
            </>)
        }
    
        function Child ({onChildCallback}){
            function handleClick(){
                onChildCallback()
            }
    
            return (
                <div onClick={handleClick}>{'this is childData'}</div>
            )
        }
    
    • 在子组件直接绘制父组件需要的DOM
      • antdesign Modal 为什么能在子组件直接设置modal的显示很隐藏的state基本和这一个思想
        * 这个可以理解父组件向子组件传递了一个函数,函数设置的状态,【而该状态就是DOM片段】 - 直接是状态设置函数 *
        * 因为万物皆可为state,那么DOM片段同样可以为State,那么这种情况就成为了可能 *
        * 不过这里有几点值得思考:设置为DOM,整个组件树都要重新渲染,可以考虑子组件Memo *
    
        function Parent (){
            const [parentData,setParentData] = useState(null)
    
            return (
                <>
                    <div>显示父级相关DOM {parentData} </div> 
                    <Child setParentData={setParentData} />
                </>
            )
        }
    
        function Child ({setParentData}){
            const [childData,setChildData] = useState('this is childData')
    
            useEffect(()=>{
                 setParentData && setParentData(<div>{childData}</div>)
            },[childData,setParentData])
    
            return <div>{'this is childData'}</div>
        }
    
        * 这个可以理解也是父组件向子组件传递了一个函数,函数返回的状态就是DOM片段 - 直接设置函数 *
        * 不过这里有几点值得思考:
            1、设置为DOM,整个组件树都要重新渲染,可以考虑子组件Memo
            2、设置函数在父组件拿到回调以后再在父组件设置状态,不是向上面一种直接在子组件设置父组件状态
         *
    
        function Parent (){
            const [parentData,setParentData] = useState(null)
    
            const handleRenderContent = useCallback((childCallbackData) => {
                setParentData(childCallbackData);
                return () => {
                    setParentData(() => null);
                };
            }, []);
    
            return (
                <>
                    <div>显示父级相关DOM {parentData} </div> 
                    <Child renderContent={handleRenderContent} />
                </>
            )
        }
    
        function Child ({renderContent}){
            const [childData,setChildData] = useState('this is childData')
    
            useEffect(() => {
                if(renderContent){
                    return renderContent(() => {
                            return (
                                <div>
                                    结合child的数据展现当前child时需要展示的数据
                                    <span>{childData}</span>
                                </div>
                            );
                    });
                }
            }, [renderContent,childData]);
    
            return <div>{'this is childData'}</div>
        }
    
    • 另外还可以借助:context,redux,发布订阅。。。等实现,本文不在枚举。