簡體   English   中英

反應父組件檢查子組件是否會呈現

[英]React parent component check if child will render

我有一個子組件,根據它的一些道具,它最終會渲染或不渲染某些東西。 孩子的渲染功能看起來像這樣:

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
  }
}

在父組件中,我渲染了幾個子組件,我需要知道其中有多少將渲染,因為根據該數量我會做或不做某事。 我不想重復從孩子到父母的條件邏輯,但我不知道如何從父母那里找出孩子是否會渲染。

你想要做的是 React 中的一種反模式。 如果我理解你的問題,孩子們的渲染輸出會影響他們父母的渲染輸出,這很可能會讓你陷入渲染循環。

我建議您讓子組件盡可能簡單,並將條件邏輯提升到父組件,這將允許您計算將在適當位置渲染的子組件數量。

如果我問錯了你的問題,請告訴我。

雖然我同意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);

現在,這將渲染你的孩子兩次,所以當你已經有一個性能繁重的方法時,這不是最好的

 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 );
 <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>

處理這個問題的一種方法是使用state

在這個CodeSandbox 示例中,我使用if/else邏輯來更新組件的state 這是在componentWillReceiveProps生命周期方法中完成的。

您的render方法已簡化為switch語句。

如果您想根據您擁有的if/else邏輯調用命令式 API,您可以在您的componentDidUpdate生命周期方法中執行此操作。 這也簡化為switch語句。

這是一個非常相關的問題,會影響任何復雜性的應用程序。 不幸的是,目前還沒有明確的方法使用 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>
);

如果您需要加載器和錯誤消息,它可能會變得更加復雜,但是我會觸發父級中的所有請求。 盡量保持簡單,易於閱讀,即使這意味着更冗長。 當您需要在幾周后返回這些文件時,您不會后悔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM