前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >组长指出了我使用react常犯的错误

组长指出了我使用react常犯的错误

作者头像
FE情报局
发布2023-01-31 11:21:39
8870
发布2023-01-31 11:21:39
举报
文章被收录于专栏:FE情报局

背景

年底了,换了项目组,新的项目组使用react,从vue到react,我只花了一天的时间,看了官方简单的文章之后,就觉得这玩意很简单啊,比起vue的那么api来说,这根本没有学习成本好吧,十分迅速的就进入了react的项目开发,并且洋洋得意,根据我多年的经验来看,这波肯定会得到领导的赏识

很快,我就做完了我的需求,把代码提交上去,组长可能确实比较闲,还review了我的代码,并且指出了一系列的问题,并告诉我说学习react最难的部分,并不是知道怎么使用它,而是要知道怎么能够编写良好,干净的react代码

主要给我提了六点错误,我相信在座的各位,可能需要对号入座

在不需要使用state的时候使用state

涉及到项目中的代码逻辑,我们将一些内容通过demo的形式展示出来

提交表单在很多场景下都需要用到,对于一些表单的提交,大多数人的代码的实现可能是以下方式

代码语言:javascript
复制
export default function App() {
  const [name, setName] = useState("");
  const submit = (e) => {
    e.preventDefault();
    console.log(name);
  };
  const change = (e) => {
    setName(e.target.value);
  };
  return (
    <div className="container">
      <form onSubmit={submit}>
        <label htmlFor="name">姓名: </label>
        <input value={name} onChange={change} type="text" id="name" />
      </form>
    </div>
  );
}

页面上有一个姓名输入框,通过state的方式将数据绑定,提交的时候从state上再把数据取到,这一点确实很像vue的双向绑定,通过state的方式实现了,看着表面没有问题,并且页面也呈现了,submit的数据也取到了

但是实际上,我们并没有在别的地方使用这个name状态,除了在提交的时候,有人会说,value也用到了,但是实际上你是可以不需要value这个字段的,只有提交的时候才会用到这个数据,所以这里完全可以不使用state,防止组件刷新

只需要通过ref改一下即可

代码语言:javascript
复制
export default function App() {
  const nameRef = useRef(null);
  const submit = (e) => {
    e.preventDefault();
    console.log(nameRef.current.value);
  };
  return (
    <div className="container">
      <form>
        <label htmlFor="name">姓名: </label>
        <input ref={nameRef} type="text" id="name" />
      </form>
      <button onClick={submit}>提交</button>
    </div>
  );
}

和之前一样,我们点提交按钮的时候获取到了最新数据,并且页面没有多次刷新

useState的回调函数

那什么情况下使用useState呢?这种在页面上呈现的内容需要使用,比如一个计数器

代码语言:javascript
复制
export default function App() {
  const [count, setCount] = useState(0);
  const submit = (val) => {
    setCount(count + val);
  };
  return (
    <div className="container">
      <button onClick={() => submit(-1)}>-1</button>
      <span>{count}</span>
      <button onClick={() => submit(1)}>+1</button>
    </div>
  );
}

表面看着没有问题,点击加减也都挺正常的,但是如果你是熟悉useState的话,你也会给setCount传递一个函数的形式,这两者表现形式似乎完全一样,感受不到区别

代码语言:javascript
复制
const submit = (val) => {
  setCount((current) => current + val);
};

那具体的区别在哪呢?在不使用回调函数的时候,如果我们连续更新状态的话,像下面这样

代码语言:javascript
复制
setCount(count + val)
setCount(count + val)

实际上页面也只会加一次,因为在这一次的更新过程中,count的值是固定的,也就是我们常说的setState是异步的原因(当你更改状态的时候,它不会立刻更新,而是等到下一次render才会更新),并且react会将state进行批处理,但是如果是函数的形式

代码语言:javascript
复制
const submit = (val) => {
  setCount((current) => current + val);
  setCount((current) => current + val);
};

就能够得到想要的结果,所以如果你想使用之前的状态来进行state值的修改,最好使用函数形式

state异步更新,useEffect的使用

通过上一个count,我们知道我们立刻获取count值的时候获取到的不是最新值

代码语言:javascript
复制
const submit = (val) => {
    setCount((current) => current + val);
    console.log(count);
  };

这时候有人就想到了useEffect,如此就获取到了新的值

代码语言:javascript
复制
useEffect(() => {
  console.log(count)
}, [count])

然后对于这一点,很多同学就将useEffect当成了vue中的watch,实现了下面的逻辑

代码语言:javascript
复制
export default function App() {
  const [user, setUser] = useState("");
  const [name, setName] = useState("");
  const [userName, setUserName] = useState("");

  useEffect(() => {
    setUserName(user + name);
  }, [user, name]);

  return (
    <div className="container">
      <input
        type="text"
        value={user}
        onChange={(e) => setUser(e.target.value)}
      />
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <span>{userName}</span>
    </div>
  );
}

咋一看好像没什么问题,并且实现了对应的功能,但是它不是最佳方式

实际完全可以不用userName这个state,直接在dom中<span>{user + name}</span>就能实现对应的效果

有时候很多同学也会使用useEffect进行下面的操作

代码语言:javascript
复制
useEffect(() => {
  fetch('#').then(d => setData(d))
}, [])

useEffect(() => {
  console.log(d)
}, [d])

那为什么你不把console.log的逻辑放在.then里面呢?

常见useEffect错误

代码语言:javascript
复制
const [user, setUser] = useState("");
const person = {
  user
}
useEffect(() => {
  console.log(person)
}, [person])

这种情况,大多数会认为useEffect会在组件初始化的时候执行一次,但实际上useEffect中的回调会执行多次,因为person是个引用类型,每次的指针地址都是变化的

这个时候你可以使用useMemo来解决这个问题

代码语言:javascript
复制
const person = useMemo(() => ({
  user
}), [user])

依赖问题

由于业务很复杂,所以在不断迭代的过程中,我们的effect通常就会变成这种情况

代码语言:javascript
复制
useEffect(() => {
 ......
}, [person, name, age, id, status, address ....])

依赖会越来越多,稍微改其中的一个点,就会执行effect大片的逻辑,这里最好能够拆分或者合并,确定要执行一个逻辑的,最好放在一个state中,比如可以将age,name,id,等基础信息放在一个state,然后这个effect依赖这一个state就可以了,进行state合并

总结

上述就是一些基础react使用者常出现的一些问题,hook确实能给我们带来很大的便利,但是有时候从vue到react,其中的一些思想还是需要做一些调整,才能更好的适应hooks的方式,我们可以多看看好的一些hooks的封装,加深一些hooks的理解,也欢迎大家关注公众号【FE情报局】,一起讨论一些技术文章

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FE情报局 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 在不需要使用state的时候使用state
  • useState的回调函数
  • state异步更新,useEffect的使用
  • 常见useEffect错误
  • 依赖问题
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档