【问题标题】:How to make a react component update when a self-updating prop changes?当自更新道具发生变化时如何进行反应组件更新?
【发布时间】:2020-07-17 08:50:18
【问题描述】:

我有一个可以自我更新的对象。假设它每秒钟都会改变它的状态。

export class Obj {

  val = 0;

  start = () => {
    setInterval(() => {
     this.update();
    }, 1000);
  }

  update = () => {
    this.val++;
  }

}

我认为(如果我错了,请纠正我)类似的替代方案是连接到数据流的对象,每隔几毫秒将其状态更改为收到的最后一个值。

我现在想要一个显示这个的反应组件(使用钩子):

function C(obj) {

  return <div>{obj.val}</div>

}

我的问题是,当obj 的值发生变化时,如何使组件C 发生变化?我可以在每次更改时使用回调,但感觉就像我只是为了 React 而污染我的模型。另一种方法是将Obj 之外的间隔移动到 React 组件中,但这可能不是我想要的,并且不会涵盖流的情况。

当组件的某些 props 更改其状态时,React 是否有标准方法来更新(基于函数的、基于钩子的)组件?

【问题讨论】:

  • 这是什么语法? obj是一个类?此外,组件在 props 更改时自行呈现

标签: javascript reactjs


【解决方案1】:

要更新 React 组件,您需要使用任何 React API、渲染组件的父级(如果没有记忆)或更改其道具。更新对象/类的值不会通知 React。

有很多方法可以让 React 感知对象的变化,就像你描述的那样。

一个不太熟悉的方法是使用this.forceUpdate,它手动强制渲染组件,它广泛用于通用库的 React 包装器。

这是一个带有钩子的用法示例:

class Obj {
  val = 0;

  start = sideEffect => {
    setInterval(() => {
      this.update();
      sideEffect();
    }, 1000);
  };

  update = () => {
    this.val++;
    console.log(this.val);
  };
}

const obj = new Obj();

const App = () => {
  const [, render] = useReducer(p => !p, false);
  useEffect(() => {
    const renderOnUpdate = () => {
      obj.start(render);
    };
    renderOnUpdate();
  }, []);

  return <>{obj.val}</>;
};

【讨论】:

    【解决方案2】:

    组件需要有一个状态,可以通过setState方法更新。当你有一个不断变化的 prop 时,从你的 react 组件中提供一个回调方法可能是有意义的,当被调用时,它会在后台执行 setState

    【讨论】:

    • 我发布的示例非常做作,使用useState 更新状态的回调就足够了。但是我已经看到,在对象状态频繁更改的一些更复杂的情况下(例如:流),这可能会产生一些竞争条件。你有这方面的经验吗?
    【解决方案3】:

    在这种情况下,组件 C 不会重新渲染,因为它的 props (obj) 从未更改过。对象是通过引用进行比较的,因为它与什么都没有发生之前的对象引用相同。

    您可以像这样使用组件C 使其重新渲染:&lt;C value={obj.val} /&gt;,因此每次obj.val 更新它都会做出相应的反应,因为它的道具现在正在改变。

    你也可以在里面有这个逻辑:

    const obj = new Obj();
    
    function C() {
      const [value, setValue] = React.useState(0);
      
      React.useEffect(() => {
        const interval = setInterval(() => {
          setValue(value + 1);
        }, 1000);
    
        return () => {
          clearInterval(interval); // don't forget to do cleanup
        }; 
      }, []);
    
      return <div>{value}</div>
    }
    

    【讨论】:

    • 这种方法确实有效。问题是并不总是可以移动对象的更新逻辑自动侧。
    猜你喜欢
    • 2022-08-07
    • 2019-10-17
    • 1970-01-01
    • 2021-02-25
    • 2023-01-04
    • 1970-01-01
    • 2022-07-18
    • 2020-09-01
    • 2021-11-03
    相关资源
    最近更新 更多