自定义使用效果第二个参数

Col*_*rdo 6 javascript reactjs

新的React API包括useEffect(),其第二个参数采用Object哪个React差异来查看组件是否已更新。

例如

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);
Run Code Online (Sandbox Code Playgroud)

[props.source]论点在哪里。

我的问题是:我可以定义一个自定义函数来运行以检查道具是否已更改吗?

我有一个自定义对象,React似乎无法告诉它何时已更改。

Iva*_*nin 7

AFAIK 目前不可能。有一些解决方法:

1)在里面手动做深度比较useEffect。存储上一个。您可以使用的值,useState或者甚至更好,useRef如下所示:https : //overreacted.io/a-complete-guide-to-useeffect/

2) 与JSON.stringify(props.source). 可以,如果数据不是太大。请注意,这stringify可能会产生不一致的结果(对象中的键更改顺序将更改输出)。

3)散列md5(props.source)(或其他一些快速/轻量级散列)。比以前更真实但更慢。

  • 视频不是免费的。说我需要注册,每月花费 250 美元或 40 美元。这里的答案至少需要 40 美元才能查看,这并不酷! (2认同)

Tho*_*dez 5

这个答案的功劳归功于 @Tholle useEffect 第二个参数中的对象,而无需将其字符串化为 JSON

const { useState, useEffect, useRef } = React;
const { isEqual } = _;

function useDeepEffect(fn, deps) {
  const isFirst = useRef(true);
  const prevDeps = useRef(deps);

  useEffect(() => {
    const isSame = prevDeps.current.every((obj, index) =>
      isEqual(obj, deps[index])
    );

    if (isFirst.current || !isSame) {
      fn();
    }

    isFirst.current = false;
    prevDeps.current = deps;
  }, deps);
}

function App() {
  const [state, setState] = useState({ foo: "foo" });

  useEffect(() => {
    setTimeout(() => setState({ foo: "foo" }), 1000);
    setTimeout(() => setState({ foo: "bar" }), 2000);
  }, []);

  useDeepEffect(() => {
    console.log("State changed!");
  }, [state]);

  return <div>{JSON.stringify(state)}</div>;
}

ReactDOM.render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

为什么使用useRef而不是useState

通过使用从 useState 返回的函数,组件将被重新渲染,这在本例中是不需要的