Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在子挂载上设置父状态是否为反模式?_Javascript_Reactjs - Fatal编程技术网

Javascript 在子挂载上设置父状态是否为反模式?

Javascript 在子挂载上设置父状态是否为反模式?,javascript,reactjs,Javascript,Reactjs,我正在使用React创建一个表单,并创建了一个组件,该组件需要根据特定类型的子元素数量呈现不同的包装器元素 例如,如果字段包装单个输入,它应该呈现一个包装器和一个。但是,如果它包装多个输入,则应呈现一个和一个 至关重要的是,子项不一定是组件的直接后代,因此使用React.children.count计算子项将不起作用 我可以通过在装入子输入时设置父字段状态轻松完成此操作,例如: const FormFieldContext = createContext({}); // Simplified

我正在使用React创建一个表单,并创建了一个
组件,该组件需要根据特定类型的子元素数量呈现不同的包装器元素

例如,如果字段包装单个输入,它应该呈现一个包装器
和一个
。但是,如果它包装多个输入,则应呈现一个
和一个

至关重要的是,子项不一定是
组件的直接后代,因此使用
React.children.count计算
子项
将不起作用

我可以通过在装入子输入时设置父字段状态轻松完成此操作,例如:

const FormFieldContext = createContext({});

// Simplified Field component
const Field = ({ label, children, ...props }) => {
  const [fieldCount, setFieldCount] = useState(0);
  const Wrapper = fieldCount > 1 ? 'fieldset' : 'div';
  const Label = fieldCount > 1 ? 'legend' : 'label';

  return (
    <Wrapper>
      <Label>{label}</Label>
      <FormFieldContext.Provider value={{ setFieldCount }}>
        {children}
      </FormFieldContext.Provider>
    </Wrapper>
  );
};

// Inside <Checkbox />
const Checkbox = ({ name, ...props }) => {
  const { setFieldCount } = useContext(FormFieldContext);

  useLayoutEffect(() => {
    setFieldCount(count => count + 1);

    return () => {
      setFieldCount(count => count - 1);
    };
  }, [setFieldCount, name]);

  return ( /** etc */ );
};



输入您的电子邮件
选择你的金属
青铜色
银币

实际上,可以递归地从
子项
道具中获取React组件树中的所有子项,当您拥有所有子项时,您可以计算出类型为
复选框
等的组件的数量,以确定应如何包装子项

可能有更优雅的方法,但在下面的代码示例中,我使用递归地
将直接子级减少为包含所有子级的平坦数组

const getChildrenRecursively = (soFar, parent) => {
    if(typeof parent === "string") return soFar.concat(parent);

    const children = Array.isArray(parent.props.children) ? 
    parent.props.children : 
    React.Children.toArray(parent.props.children);

  const childCount  = children.length;

    if(childCount <= 0) {
    return soFar.concat(parent);
  } else {
    return soFar.concat([parent], children.flatMap(child => getChildrenRecursively([], child)));
  }
}

它确实“感觉”有点像反模式,并将表单和字段组件连接在一起。我会为Fieldset变体创建一个单独的组件。谢谢你的建议。我没有想到你可以递归地得到孩子——这绝对是一种选择。
const getChildrenRecursively = (soFar, parent) => {
    if(typeof parent === "string") return soFar.concat(parent);

    const children = Array.isArray(parent.props.children) ? 
    parent.props.children : 
    React.Children.toArray(parent.props.children);

  const childCount  = children.length;

    if(childCount <= 0) {
    return soFar.concat(parent);
  } else {
    return soFar.concat([parent], children.flatMap(child => getChildrenRecursively([], child)));
  }
}