Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 优秀博客阅读摘要 & 总结 #18

Open
venaissance opened this issue Feb 13, 2021 · 0 comments
Open

React 优秀博客阅读摘要 & 总结 #18

venaissance opened this issue Feb 13, 2021 · 0 comments

Comments

@venaissance
Copy link
Owner

1. 《When to useMemo and useCallback》

Performance optimizations are not free. They ALWAYS come with a cost but do NOT always come with a benefit to offset that cost.
Therefore, optimize responsibly.

优化并不是免费的。(在优化上)你往往失去的比得到的更多。所以我们需要负责任地优化。

So when should I useMemo and useCallback?
There are specific reasons both of these hooks are built-into React:

  1. Referential equality
  2. Computationally expensive calculations

所以我应该什么时候使用 useMemo 和 useCallback?
这两个 hooks 内置于 React 都有特别的原因:

  1. 需要让引用相等
  2. 性能十分昂贵的计算

2. 《A Complete Guide to useEffect》

  1. Each Render Has Its Own Props and State 每次渲染都有它自己的 Props 和 State
  2. Each Render Has Its Own Event Handlers 每次渲染都有它自己的事件处理函数
  3. Each Render Has Its Own Effects, and Everything.. 每次渲染都有它自己的副作用,以及一切
  4. Two Ways to Be Honest About Dependencies 我们应该诚实面对依赖的两条途径
    • include all the values 包含全部,别遗漏任何一个
    • change our effect code to have fewer of dependencies 通过改变我们的代码,去减少依赖数量
  5. How to Change? 如何改变呢?
  • Making Effects Self-Sufficient 让副作用“自给自足”

E.g.

 useEffect(() => {
    const id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
  }, [count]);

To

  useEffect(() => {
    const id = setInterval(() => {
      setCount(c => c + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []);
  • Decoupling Updates from Actions by using useReducer 使用 useReducer 让更新与动作分离
const [state, dispatch] = useReducer(reducer, initialState);
const { count, step } = state;

useEffect(() => {
  const id = setInterval(() => {
    dispatch({ type: 'tick' }); // Instead of setCount(c => c + step);
  }, 1000);
  return () => clearInterval(id);
}, [dispatch]);

const initialState = {
  count: 0,
  step: 1,
};

function reducer(state, action) {
  const { count, step } = state;
  if (action.type === 'tick') {
    return { count: count + step, step };
  } else if (action.type === 'step') {
    return { count, step: action.step };
  } else {
    throw new Error();
  }
}

React guarantees the dispatch function to be constant throughout the component lifetime. So the example above doesn’t ever need to resubscribe the interval.
(You may omit dispatch, setState, and useRef container values from the deps because React guarantees them to be static. But it also doesn’t hurt to specify them.)

You may be wondering: how can this possibly work? How can the reducer “know” props when called from inside an effect that belongs to another render? The answer is that when you dispatch, React just remembers the action — but it will call your reducer during the next render. At that point the fresh props will be in scope, and you won’t be inside an effect.

This is why I like to think of useReducer as the “cheat mode” of Hooks. It lets me decouple the update logic from describing what happened. This, in turn, helps me remove unnecessary dependencies from my effects and avoid re-running them more often than necessary.

  1. Moving Functions Inside Effects 把函数放到 useEffect 里,可以避免由于函数增长导致的依赖遗漏问题

  2. 如果有多个 useEffect 时,函数不用每个都放进去,可以用 useCallback 包裹起来,当函数参数变化时,自动生成新的函数,然后也会触发依赖此函数的 useEffect 执行。这样可以触发数据流的自动变化。

With classes, function props by themselves aren’t truly a part of the data flow.

With useCallback, functions can fully participate in the data flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant