react jsx和{props.children}渲染的区别?

https://codesandbox.io/s/nift... 沙箱
为什么使用{props.children}父组件更改状态子组件不会触发render?

const ComA = () => {
  console.log("ComA render");
  return <div>ComA</div>;
};

const ComB = () => {
  console.log("ComB render");
  return <div>ComB</div>;
};

function App(props) {
  console.log("App render");
  const [text, setText] = useState("text");
  return (
    <div className="App">
      <ComA />
      <ComB />
      <button onClick={setText.bind(null, "update_text"+Math.random())}>
        updateText({text})
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

打印:
App render
ComA render
ComB render

const ComA = () => {
  console.log("ComA render");
  return <div>ComA</div>;
};

const ComB = () => {
  console.log("ComB render");
  return <div>ComB</div>;
};
function App(props) {
  console.log("App render");
  const [text, setText] = useState("text");
  return (
    <div className="App">
      {props.children}
      <button onClick={setText.bind(null, "update_text" + Math.random())}>
        updateText({text})
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <App>
    <ComA />
    <ComB />
  </App>,
  rootElement
);

打印:
App render

阅读 5k
2 个回答

整理一下你的结论:
情况1,调用props.children,ComA 和 ComB不会重新渲染;
情况2,直接在App组件中的render函数内嵌ComA和ComB,会引发重新渲染;

情况1

ComA 和 ComB在App的render函数中是以props.children的形式体现出来的。这个props是App的props,而App渲染时,其props并未变化,相应的props.children,它是ComA 和 ComB的jsx形式,也没有变化,也就是说ComA 和 ComB的props同样没有变化,所以不会重新渲染。

情况2

ComA 和 ComB的形式在App的render函数中是<ComA />、<ComB />这最终会被编译成

React.createElement(ComA, null)
React.createElement(ComB, null)

它们执行后返回的时包含<ComA />和<ComB />props的一个对象(ReactElement)

export function createElement(type, config, children) {
  // 重点在这里,重新声明了props属性的引用
  const props = {};
  ...
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
 );
}

也就是说,返回结果是一个ReactElement全新的引用,而它里面的props也是一个全新的对象,这也就意味着<ComA />和<ComB />的props变了,所以它们会重新渲染。

????? 你提供的代码,不是两者都打印的一样么?
最后一行忘注释,这种失误再怎么也能排查出来吧。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题