【问题标题】:React TypeScript containment parent passing props to childrenReact TypeScript 包含父级将道具传递给子级
【发布时间】:2023-01-13 01:56:29
【问题描述】:

我已经尝试了几个小时,但还没有找到令人满意的解决方案。我想让这个包装器包含一些状态,然后我可以将其传递给它的子级或渲染其他东西。

我想做类似这个抽象示例的事情。我能做些什么吗?

const MyChild = (props:{state:boolean}) => {
   return <Text>`the state is ${props.state}`</Text>
}

const StateWrapper = ({children}:{children:React.ReactNode}) => {
   const hookState:boolean|null = useHookState()
   if (null) return <Loading />
   return {children} <-- with {state:boolean}
}

const App = () => {
   return <StateWrapper><MyChild /><StateWrapper>
}

【问题讨论】:

  • 它必须是&lt;StateWrapper component={MyChild} /&gt;才能工作。

标签: reactjs typescript


【解决方案1】:

此类问题的常见模式是“Render Props”方法。 “状态包装器”对象采用将其数据传递给其他对象进行渲染的道具。这样您就不必对状态数据进行任何奇怪的更改或复制,并且名称不必完美对齐,以便将来轻松交换其他组件。

const MyChild = (props: {state: boolean}) => {
   return <Text>`the state is ${props.state}`</Text>
}

const StateWrapper = ({children}:{children: (state: boolean) => React.ReactNode}) => {
   const hookState:boolean|null = useHookState()
   if (null) return <Loading />
   return children(state);
}

const App = () => {
  return (
    <StateWrapper>
      {(state) => (<MyChild state={state}/>)}
    </StateWrapper>
  );
}

查看更多:https://reactjs.org/docs/render-props.html

【讨论】:

  • 这似乎工作正常,如果有任何问题会更新。
  • 会注意到我必须将 return children(state) 包装在一个片段中
【解决方案2】:

3 种带有 ref 的包装器,并在打字稿中添加了道具: 沙盒演示:https://codesandbox.io/s/wrapper-2kn8oy?file=/src/Wrapper.tsx

import React, { cloneElement, forwardRef, useRef, useState  } from "react";
interface MyChild extends React.ReactElement {
    ref?:React.Ref<HTMLDivElement>|undefined
}
interface MyProps {
    children:MyChild|MyChild[],
    added:string,
}

const Wrapper1 = ({ children, added }: MyProps) => {
    const e =
        Array.isArray(children) ?
            children.map((child) => {
                return cloneElement(child, { added: added })
            }) :
            cloneElement(children)
    return <>
        {e}
    </>
}

const Wrapper2 = ({ children, added }:MyProps) => {

    const e =
        Array.isArray(children) ?
            children.map((child) => {
                return <child.type  {...child.props} added={added} ref={child.ref} />
            }) :
            children?<children.type {...children.props} added={added} ref={children.ref}/>:null
    //console.log("2:",e)
    if(!Array.isArray(children))console.log(children.ref)
    return <>
        {e}
    </>
}
const Wrapper3 = ({ children, added }:{children:any,added:any}) => {
    return <>
        {children(added)}
    </>
}

const Mydiv = forwardRef((props: any, ref?: any) =>
    <div ref={ref}>Origin:{props.message},Added:{props.added ?? "None"}</div>
)
const Container = () => {
    const ref1 = useRef<HTMLDivElement>(null)
    const ref2 = useRef<HTMLDivElement>(null)
    const ref3 = useRef<HTMLDivElement>(null)
    const [refresh, setRefresh] = useState(1)
    const setColor = () => {
        console.log("ref1:", ref1.current, "ref2:", ref2.current, "ref3:", ref3.current)
        if (ref1.current) ref1.current.style.color = "red"
        if (ref2.current) ref2.current.style.color = "red"
        if (ref3.current) ref3.current.style.color = "red"
    }

    return <>
        <button onClick={setColor}>Change Color</button>
        <button onClick={() => setRefresh((n) => n + 1)}>Refresh page</button>
        <div>{`state:${refresh}`}---state:{refresh}</div>

        <Wrapper1 added="Wrapper1 added">
            <Mydiv ref={ref1} message={`MyDiv 1 with Ref,parent state:${refresh}`} />
            <Mydiv message={`MyDiv 1 without ref,parent state:${refresh}`} />
        </Wrapper1>

        <Wrapper2 added="Wrapp2 added">
            <Mydiv ref={ref2} message={`MyDiv 2 with Ref,parent state:${refresh}`} />     
            <Mydiv message={`MyDiv 2 without ref,parent state:${refresh}`} />
        </Wrapper2>

        <Wrapper3 added="Wrapp3 added">
            {(added: any) => (<>
                <Mydiv ref={ref3} message={`MyDiv 3 with Ref,parent state:${refresh}`} added={added} />
                <Mydiv message={`MyDiv 3 without Ref,parent state:${refresh}`} added={added} />
            </>
            )}
        </Wrapper3>

    </>
}
export default Container

【讨论】:

  • 这仍然会带来一些 TypeScript 错误。即 map 在 ReactPortal 上不存在,而 child 是明确的。我正在尝试玩它,但我还没有找到解决方案
  • 忘记添加包装器。更新它
  • 还是不行
  • 抱歉,我在外面,所以没有验证。再次更新。
  • 沙箱服务器有一些问题,我稍后会粘贴一个有效的沙箱链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-13
  • 2020-09-09
  • 1970-01-01
  • 2020-12-31
  • 2018-03-09
相关资源
最近更新 更多