反应父组件检查子项是否将呈现

时间:2018-02-15 13:57:57

标签: javascript reactjs

我有一个子组件,根据它的一些道具最终会呈现某些东西。孩子们的渲染功能看起来像这样:

render() {
  if (props.a == 'foo' && props.b == 'bar') {
    return (<p> Hey There </p>);
  } else if {props.a == 'z') {
    return (<p> Hey There </p>);
  } // more conditions
  } else {
    return null
  }
}

在父组件中,我渲染了几个子组件,我需要知道它们中有多少会呈现,因为根据这个数字我会做什么或不做。我不想重复从孩子到父母的条件逻辑,但我不知道如何从父母那里知道孩子是否会被渲染。

4 个答案:

答案 0 :(得分:4)

你想要做的是在React中有点反模式。 如果我理解你的问题,子渲染输出会影响他们的父渲染输出,这可能会让你陷入渲染循环。

我建议你让孩子们的组件尽可能简单,并将条件逻辑提升到父母,这样你就可以计算你将要渲染的孩子数量。

如果我的问题出错了,请告诉我。

答案 1 :(得分:1)

虽然我同意perpetualjourney的回答,但我认为我可以给你一个计算孩子的可能性。

最简单的方法是先将子项的渲染保存到变量中,然后再渲染该结果。

var kids = this.props.items.map( (k, i) => <Kid condition={k} key={i} /> );
var totalKids = kids.reduce( (k, i) => k + (i.type( i.props ) ? 1 : 0), 0);

现在,这会让你的孩子两次,所以当你已经有一个性能沉重的方法时,这不是最好的

&#13;
&#13;
const Kid = ({ condition }) => condition % 3 === 0 ? <h1>{ condition }</h1> : null;

class ConditionalKids extends React.Component {
  render() {
    var kids = this.props.items.map( (k, i) => <Kid condition={k} key={i} /> );
    var totalKids = kids.reduce( (k, i) => k + (i.type( i.props ) ? 1 : 0), 0);
    return <div>
      <p>Rendered in total { totalKids }</p>
      { kids }
    </div>;
  }
}

const items = [...new Array(5)].map( i => parseInt( Math.random() * 10 ) );
console.log( items );

const target = document.querySelector('#container');
ReactDOM.render( <ConditionalKids items={items} />, target );
&#13;
<script id="react" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.js"></script>
<script id="react-dom" src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.js"></script>
<div id="container"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

处理此问题的一种方法是使用3.14 == 3.1400

在此CodeSandbox example中,我使用state逻辑更新组件的if/else。这是在state生命周期方法中完成的。

您的componentWillReceiveProps方法已简化为render语句。

如果您想根据switch逻辑调用命令式API,可以在if/else生命周期方法中执行此操作。这也简化为componentDidUpdate语句。

答案 3 :(得分:0)

这是一个非常相关的问题,会影响任何复杂性的应用程序。不幸的是,目前还没有明确的方法使用React对此建模。我已经做了很多React,并会推荐@perpetualjourney所说的话:将逻辑提升给一个共同的父母。有时,您需要将其向上移动,但不要像React.Children.mapReact.Context那样弄乱它们,因为它们会在组件之间建立依赖关系,并且使您难以移动它们如果需要的话。

const hasA = computeHasA({ ... });
const hasB = computeHasB({ ... });
const hasAny = hasA || hasB;

if (hasAny) {
  return (
    <Tabs>
      {hasA && <Tab title="A">Some content</Tab>}
      {hasB && <Tab title="B">Another content</Tab>}
    </Tabs>

  );
}

例如,当您真的无法向上移动逻辑时,如果孩子们提出网络请求(这可能是一个极端的情况),我建议您传递一个用于报告他们是否有内容并存储的道具。进入父母的状态:

const [numberOfRenderedChildren, setNumberOfRenderedChildren] = useState(0);

const incrementNumberOfRenderedChildren = () => {
  // Use a callback to prevent race conditions
  setNumberOfRenderedChildren(prevValue => prevValue + 1);
};


return (
  <MyContainer isVisible={numberOfRenderedChildren > 0}>
    {items.map(item => (
      <ComplexChild
        key={item.id}
        // Avoid spreading props like ...item. It breaks semantics
        item={item}
        reportHasContent={incrementNumberOfRenderedChildren}
      />
    )}
  </MyContainer>
);

如果您需要加载程序和错误消息,它可能会变得更加复杂,但是我会触发父级中的所有请求。即使它意味着更多的冗长性,也请尝试使其简单,易于阅读。几周后需要返回这些文件时,您将不会后悔。