不要无脑使用useEffect

不要在props 或 state 改变的时候去更新state

Updating state based on props or state
You don’t need Effects to transform data for rendering. For example, let’s say you want to filter a list before displaying it. You might feel tempted to write an Effect that updates a state variable when the list changes. However, this is inefficient. When you update the state, React will first call your component functions to calculate what should be on the screen. Then React will “commit” these changes to the DOM, updating the screen. Then React will run your Effects. If your Effect also immediately updates the state, this restarts the whole process from scratch! To avoid the unnecessary render passes, transform all the data at the top level of your components. That code will automatically re-run whenever your props or state change

如果你要在展示一个列表之前先去过滤出要展示的数据, 你可能想当list改变的时候用个Effect去更新状态,但是当你更新state的时候,react会先调用你的组件函数去计算要展示在屏幕上的内容,并且把这些改变提交的给dom然后重绘,接着react又去跑你的useEffect, 如果你的Effect是立马更新state的,那么就会马上再次渲染重绘一次,

function Form() {
  const [firstName, setFirstName] = useState('Taylor');
  const [lastName, setLastName] = useState('Swift');

  // 🔴 Avoid: redundant state and unnecessary Effect
  const [fullName, setFullName] = useState('');
  useEffect(() => {
    setFullName(firstName + ' ' + lastName);
  }, [firstName, lastName]);
  // ...
}

为了避免这种情况,应该把这个过滤数据的过程放在组件顶部,这样就会在state更新的时候自动刷新数据,且不会导致重新渲染

function Form() {
  const [firstName, setFirstName] = useState('Taylor');
  const [lastName, setLastName] = useState('Swift');
  // ✅ Good: calculated during rendering
  const fullName = firstName + ' ' + lastName;
  // ...
}

When something can be calculated from the existing props or state,
don’t put it in state. Instead, calculate it during rendering.
也就是说你要根据组件参数和state去得到一个数据的话,不要再用一个useeffect去监听他们的变化然后再用一个state更新,直接放在外面,每次渲染的时候自然会计算

如果你的计算量很大,不想直接放在渲染的时候每次都计算,可以放在usememo中

import { useMemo, useState } from 'react';

function TodoList({ todos, filter }) {
  const [newTodo, setNewTodo] = useState('');
  const visibleTodos = useMemo(() => {
    // ✅ Does not re-run unless todos or filter change
    return getFilteredTodos(todos, filter);
  }, [todos, filter]);
  // ...
}

这样如果跟上次的值没有发生改变,就不会再去重新计算了

不要在prop改变的时候更新所有state

Resetting all state when a prop changes

export default function ProfilePage({ userId }) {
  const [comment, setComment] = useState('');

  // 🔴 Avoid: Resetting state on prop change in an Effect
  useEffect(() => {
    setComment('');
  }, [userId]);
  // ...
}

Instead, you can tell React that each user’s profile is conceptually a different profile by giving it an explicit key. Split your component in two and pass a key attribute from the outer component to the inner one:
把上面的组件分成两个,然后通过一个key值告诉react去区分每个用户的资料

export default function ProfilePage({ userId }) {
  return (
    <Profile
      userId={userId}
      key={userId}
    />
  );
}

function Profile({ userId }) {
  // ✅ This and any other state below will reset on key change automatically
  const [comment, setComment] = useState('');
  // ...
}

参考链接:
https://react.dev/learn/you-might-not-need-an-effect#sharing-logic-between-event-handlers

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值