React Hooks 钩子函数错误用法,你还在犯这些错误吗

React Hooks 常见错误

前言

本片文章主要是在写react hooks的时候,遇到的常见错误的写法,和错误。也是一个对只是的巩固和总结。


错误一

上代码:正确写法

function TestReactHooksError() {
    
    
  const [test, setTest] = useState('test');
  useEffect(() => {
    
    
    if(test) {
    
    
      console.log(test)
    }
  }, [test]);
  return (
    <div>
      <button onClick={
    
    ()=>setTest(test + 1)}>{
    
    test}click</button>
    </div>
  );
}
export default TestReactHooksError

解析:
功能,点击按钮,按钮文案改动,并且控制台打印文案结果。
稍作改动:

function TestReactHooksError() {
    
    
  const [test, setTest] = useState('test');
  if (test) {
    
    
    useEffect(() => {
    
    
      console.log(test)
    }, [test]);
  }
  return (
    <div>
      <button onClick={
    
    () => setTest(test + 1)}>{
    
    test}click</button>
    </div>
  );
}
export default TestReactHooksError

可以看到报错了:
在这里插入图片描述
搜狗翻译:
React钩子“useEffect”被有条件地调用。React挂钩必须在每个组件渲染中以完全相同的顺序调用
正常翻译:
就是钩子函数必须按顺序执行,因为底层是按顺序执行的,所以如果加入判断的话,可能有不可预知的错误。


错误二

上代码:正确写法

function TestReactHooksError() {
    
    
  const [test, setTest] = useState([1, 2, 3, 4, 5]);
  useEffect(() => {
    
    
    consoleLog()
  }, []);
  const consoleLog = (value) => {
    
    
    for (let i = 0, len = test.length; i < len; i++) {
    
    
      console.log(test[i])
    }
  }
  return (
    <div>
      {
    
    
        test.map((item) => {
    
    
          return <span key={
    
    item}>{
    
    item}</span>
        })
      }
    </div>
  );
}
export default TestReactHooksError

解析:
功能,渲染列表,并且控制台打印结果。
稍作改动:

function TestReactHooksError() {
    
    
  const [test, setTest] = useState([1,2,3,4,5]);
  for (let i=0, len = test.length; i < len; i++) {
    
    
    useEffect(() => {
    
    
      console.log(test[i])
    }, [test[i]]);
  }
  
  return (
    <div>
      {
    
    
        test.map((item)=>{
    
    
          return <span key={
    
    item}>{
    
    item}</span>
        })
      }
    </div>
  );
}
export default TestReactHooksError

报错:
在这里插入图片描述
可以看到结果都正常打印了,但是报错了。
搜狗翻译:
React挂钩“useEffect”可以执行多次。可能是因为它是在循环中调用的。React挂钩必须在每个组件渲染中以完全相同的顺序调用
正常翻译:
不能在循环中使用hooks,因为还是可能会导致执行顺序错误,导致结果错误。


错误三

上代码: 正确写法

function TestReactHooksError() {
    
    
  const [testState, setTestState] = useState('testState')
  const clickState = () => {
    
    
    console.log(testState)
  }
  return (
    <div>
      <button onClick={
    
    ()=>clickState()}>click</button>
    </div>
  );
}
export default TestReactHooksError

解析:
功能,点击按钮控制台打印结果。
稍作改动:

function TestReactHooksError() {
    
    
  const clickState = () => {
    
    
    const [testState, setTestState] = useState('testState')
    console.log(testState)
  }
  return (
    <div>
      <button onClick={
    
    ()=>clickState()}>click</button>
    </div>
  );
}
export default TestReactHooksError

报错:
在这里插入图片描述
搜狗翻译:
React挂钩“useState”在函数“clickState”中调用,该函数既不是React函数组件,也不是自定义React挂钩函数。React组件名称必须以大写字母开头。React挂钩名称必须以单词“use”开头
正常翻译:
这个翻译的很明白,就是不能在普通函数中使用,因为react不会理解它是一个组件或者是自定义hooks。


错误四

上代码: 错误写法

扫描二维码关注公众号,回复: 15848262 查看本文章
class MyComponent extends React.Component {
    
    
  constructor(props) {
    
    
    super(props);
    this.state = {
    
    
      testState: 'testState',
    };
  }

  useEffect(() => {
    
    
    console.log(this.state.testState)
  }, [this.state.testState]);

  render() {
    
    
    return (
      <div>
        <p>You clicked {
    
    this.state.testState} times</p>
        <button onClick={
    
    () => this.setState({
    
     testState: this.state.testState + 1 })}>
          Click
        </button>
      </div>
    );
  }
}

报错:
在这里插入图片描述
报错语法格式错误。所以不能混合使用


错误五

正确的写法:

function TestReactHooksError() {
    
    
  const [testState, setTestState] = useState('testState')
  function clickState() {
    
    
    console.log(testState)
  }
  return (
    <div>
      <button onClick={
    
    () => setTestState(testState + 1)}>{
    
    testState}</button>
      <button onClick={
    
    () => clickState()}>click</button>
    </div>
  );
}
export default TestReactHooksError

稍作修改:

function TestReactHooksError() {
    
    
  const [testState, setTestState] = useState('testState')
  function clickState() {
    
    
    console.log(testState)
  }
  return (
    <div>
      <button onClick={
    
    () => setTestState(testState + 1)}>{
    
    testState}</button>
      <button onClick={
    
    clickState}>click</button>
    </div>
  );
}
export default TestReactHooksError

在 JSX 的事件处理程序中调用函数时,应该传递函数本身而不是函数的返回值。改为 onClick={() => handleClick()} 或者将 handleClick 函数定义在组件外部并将其作为 prop 传递给组件。由于当前的写法每次渲染都会创建一个新的函数和事件处理程序,因此会导致浪费和性能问题。
注意:

当然在最新的版本中不会有这个问题因为,React 已经对函数事件处理程序进行了自动绑定,所以在最新版本中不会出现这个问题。这是因为最新版本的 React 使用了异步渲染机制,将多次渲染时创建的函数缓存起来进行重用,从而避免了性能问题。


错误六

使用useEffect时没有传入依赖项,这可能会导致无限制地执行useEffect,当然如果你就是为了重复执行可以跳过这个。
正确写法:

function TestReactHooksError() {
    
    
  const [test, setTest] = useState('test');
  useEffect(() => {
    
    
    console.log(test)
  }, [test]);
  return (
    <div>
      <button onClick={
    
    ()=>setTest(test + 1)}>{
    
    test}click</button>
    </div>
  );
}
export default TestReactHooksError

稍作修改:

function TestReactHooksError() {
    
    
  const [test, setTest] = useState('test');
  useEffect(() => {
    
    
    console.log(test)
  });
  return (
    <div>
      <button onClick={
    
    ()=>setTest(test + 1)}>{
    
    test}click</button>
    </div>
  );
}
export default TestReactHooksError

修改之后,如果之后再加入其他按钮渲染数据,当其他数据变化时,还是会执行useEffect,所以需要正确的添加,依赖项。


错误七

定时器
上代码:正确的写法
分别使用setTimeout和setInterval

function TestReactHooksError() {
    
    
  const [timer, setTimer] = useState(0);
  const [timerS, setTimerS] = useState(0);
  useEffect(() => {
    
    
    setTimeout(() => {
    
    
      setTimer(timer + 1)
    }, 1000)
  }, [timer]);
  useEffect(() => {
    
    
    setInterval(() => {
    
    
      setTimerS(timerS => timerS + 1)
    }, 1000)
  }, []);
  return (
    <div>
      {
    
    timer}-{
    
    timerS}
    </div>
  );
}
export default TestReactHooksError

但是这样写有一个问题,如果仔细看页面计时显示会发现两个时间有偏差。setTimeout会慢一些,但是这也不难分析,因为setTimeout 和 setInterval 的执行方式是不同的。setTimeout 在每次计时器更新时都会重新创建一个新的计时器,而 setInterval 只会在组件挂载时创建一个计时器。因此,setInterval 的计时器会一直运行,而 setTimeout 的计时器则会受到上一个计时器执行时间的影响,可能会出现延迟。另外,由于 setTimeout 是在依赖数组中的 timer 更新时执行的,当 timer 发生变化时,会重新创建一个新的计时器,这可能会导致计时器的执行时间出现偏差。
说简单点就是,setInterval 每次只是在设定的时间后马上执行,而setTimeout需要依赖数据变化并且每次都重新创建,所以会慢一些

稍作修改
错误的写法:

useEffect(() => {
    
    
  setInterval(() => {
    
    
    setTimerS(timerS + 1)
    console.log(timerS)
  }, 1000)
}, [timerS]);

可以看到页面显示抽搐的时间
在这里插入图片描述

总结

先这么多文章还会更新。。。
如有问题欢迎指出,感谢

猜你喜欢

转载自blog.csdn.net/qq_43205326/article/details/130391955
今日推荐