【问题标题】:Is it possible to add ref to the props.children elements?是否可以将 ref 添加到 props.children 元素?
【发布时间】:2020-12-18 14:38:57
【问题描述】:

我有一个FormInput组件,呈现如下。

<Form>
   <Field />
   <Field />
   <Field />
</Form>

Form 组件将在此处充当包装器组件,并且此处未设置 Field 组件引用。我想遍历 Form 组件中的 props.children 并希望为每个孩子分配一个 ref 属性。有没有可能做到这一点?

【问题讨论】:

    标签: javascript reactjs react-redux react-hooks


    【解决方案1】:

    您需要Form 来使用React.ChildrenReact.cloneElement API 注入您的引用:

    const FunctionComponentForward = React.forwardRef((props, ref) => (
      <div ref={ref}>Function Component Forward</div>
    ));
    
    const Form = ({ children }) => {
      const childrenRef = useRef([]);
    
      useEffect(() => {
        console.log("Form Children", childrenRef.current);
      }, []);
    
      return (
        <>
          {React.Children.map(children, (child, index) =>
            React.cloneElement(child, {
              ref: (ref) => (childrenRef.current[index] = ref)
            })
          )}
        </>
      );
    };
    
    const App = () => {
      return (
        <Form>
          <div>Hello</div>
          <FunctionComponentForward />
        </Form>
      );
    };
    

    【讨论】:

    • 我收到这个警告 index.js:1 警告:函数组件不能被赋予参考。尝试访问此 ref 将失败。你的意思是使用 React.forwardRef() 吗?
    • 在我的示例中,我将 ref 传递给 div,当您传递给函数组件时,您需要使用 forwardRef 或使用其他 prop(如 innerRef)并传递 ref。
    • 我已经添加了一个例子,你可以寻找“将引用传递给函数组件”。
    【解决方案2】:

    您可以使用React Docs 中显示的两种方式之一来映射子项基于它创建新的组件实例。

    • 使用React.Children.mapReact.cloneElement(这样可以保留原始元素的key 和ref)

    • 或仅使用React.Children.map(仅保留来自原始组件的引用)

    function useRefs() {
      const refs = useRef({});
    
      const register = useCallback((refName) => ref => {
        refs.current[refName] = ref;
      }, []);
    
      return [refs, register];
    }
    
    function WithoutCloneComponent({children, ...props}) {
    
     const [refs, register] = useRefs(); 
    
     return (
        <Parent>
         {React.Children.map((Child, index) => (
           <Child.type 
             {...Child.props}
             ref={register(`${field-${index}}`)}
             />
        )}
        </Parent>
     )
    }
    
    function WithCloneComponent({children, ...props}) {
    
     const [refs, register] = useRefs(); 
    
     return (
        <Parent>
         {
           React.Children.map((child, index) => React.cloneElement(
             child, 
             { ...child.props, ref: register(`field-${index}`) }
           )
        }
        </Parent>
     )
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 2020-04-30
      • 2020-06-11
      • 2013-07-09
      • 2014-01-11
      • 1970-01-01
      相关资源
      最近更新 更多