【问题标题】:React: Why are these components not updated when useState changes? (components rendered after the app is mounted)React:为什么这些组件在 useState 发生变化时没有更新? (应用挂载后渲染的组件)
【发布时间】:2020-04-24 16:15:48
【问题描述】:

一旦应用挂载,组件就会被渲染(原因是这些组件需要插入到获取的纯 HTML 中)

我看到状态发生了变化,但元素只是没有对此做出反应

有什么解决办法吗?

codesandbox

import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";

export default function App() {
  const [elements, setElements] = useState("none");

  useEffect(() => {
    console.log("global useEffect: " + elements);
  }, [elements]);

  const Input = ({ setElements }) => (
    <>
      <input
        type="text"
        onChange={e => {
          setElements(e.target.value);
        }}
      />
      <div>{elements}</div>
    </>
  );
  const Elements = ({ elements }) => {
    useEffect(() => {
      console.log("Elements useEffect: " + elements);
    }, [elements]);
    return <span>{elements}</span>;
  };
  const Elements2 = ({ elements }) => <span>{elements}</span>;

  useEffect(() => {
    console.log("useEffect first time");
    ReactDOM.render(
      <Elements elements={elements} />,
      document.getElementById("elements")
    );
    ReactDOM.render(
      <Elements2 elements={elements} />,
      document.getElementById("elements2")
    );
    ReactDOM.render(
      <Input setElements={setElements} />,
      document.getElementById("inputId")
    );
  }, []);

  // need to split plainhtml, otherwise codesandbox
  // ...gives an error that is IMO a bug
  const plainhtml1 = `
  <div>
  <div>This plain html has been fetched</div>
  <div id="inputId" />
  </div>
  `;
  const plainhtml2 = `
  <div>
  <div>number of elements:</div>
  <div id="elements" />
  </div>
  `;
  const plainhtml3 = `
  <div>
  <div>number of other elements:</div>
  <div id="elements2" />
  </div>
  `;

  return (
    <div>
      <h1>Hello CodeSandbox</h1>
      <div dangerouslySetInnerHTML={{ __html: plainhtml1 }} />
      <div dangerouslySetInnerHTML={{ __html: plainhtml2 }} />
      <div dangerouslySetInnerHTML={{ __html: plainhtml3 }} />
    </div>
  );
}

【问题讨论】:

  • 您的组件定义在另一个组件内部是非常不寻常的;如果你这样做是为了让这些可以与父级共享状态,那将不会很好地工作;您需要将任何共享状态作为道具传递,或者使用上下文等机制。
  • 刚刚用外部组件进行了测试,但问题仍然存在(如果这就是您的意思)
  • 我认为这是因为您多次调用ReactDOM.render 的useEffect 在其依赖数组中没有elements
  • @azium 绝对正确,非常感谢!我可以看到 Finesse 已经回答了这个问题

标签: javascript reactjs react-dom use-effect use-state


【解决方案1】:

元素不知道App 状态发生变化时会发生变化。使用这样的效果告诉他们更改:

useEffect(() => {
   ReactDOM.render(
    <Elements elements={elements} />,
    document.getElementById("elements")
  );
  ReactDOM.render(
    <Elements2 elements={elements} />,
    document.getElementById("elements2")
  );
  ReactDOM.render(
    <Input setElements={setElements} />,
    document.getElementById("inputId")
  );
}, [elements, setElement]);

每次elementssetElements 值发生变化时,React 都会调用效果(从而重新渲染元素)。实际上,由于您具有非常相似的效果,您只需将elements 添加到其依赖项列表(第二个参数中的数组)即可。

【讨论】:

  • 非常感谢,这是否意味着每次元素更改时都必须进行渲染?会说这不可能是这样的
  • 是的,这就是 React 的工作原理。如果元素是普通的Appchildren,它的工作原理是一样的。但 React 会先比较虚拟 DOM,然后只将所需的更改应用到真实 DOM。
猜你喜欢
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 2020-03-02
  • 2017-12-26
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多