React开发者注意 - 这些常见错误你一定要避免
2023-04-08
最近code review做的比较多,发现团队内同学(包括我自己)会犯一些常见的错误。这些错误可能会导致代码低效、难以维护,甚至会导致隐藏的BUG。本文将介绍React开发中的几个常见错误,以及如何避免它们。话不多说,让我们开始吧!
错误一:通过useEffect + useState实现派生状态
function Test(props) { const [isOdd, setIsOdd] = useState(false) useEffect(() => { setIsOdd(props.number % 2 === 1) }, [props.number]) return <div>{isOdd ? 'Yes' : 'No' }</div>}
这里的问题在于 useEffect
是在组件渲染后再执行的,而 setCount
又会导致组件重新渲染。所以这里其实多了一次没有必要的渲染。
解法也非常简单,如下
function Home(props) { const isOdd = props.number % 2 === 1 return <div>{isOdd ? 'Yes' : 'No' }</div>}
isOdd
状态是完全和props.number
挂钩的,我们只需要基于props
根据我们的逻辑去计算一个新的值就可以了。如果这个计算比较耗时,那我们还可以通过 useMemo
做缓存
function Home(props) { const isOdd = useMemo(() => { return someExpensiveCalculate(props.number) }, [props.number]) return <div>{isOdd ? 'Yes' : 'No' }</div>}
错误二:在组件内部定义组件
function Test() { const [value, setValue] = useState('') const Count = () => { return <h1>count 1</h1> } return ( <div> <input value={value} onChange={e => setValue(e.target.value)} /> <Count /> </div> )}
<Count />
这么写咋一看好像没啥问题。我们给 <Count />
加点逻辑
function Test() { const [value, setValue] = useState('') const Count = () => { const [count, setCount] = useState(0); return ( <div> <h1>count {count}</h1> <button onClick={() => setCount((c) => c + 1)}>add</button> </div> ); }; return ( <div> <input value={value} onChange={e => setValue(e.target.value)} /> <Count /> </div> )}
可以多点击几次「add」按钮,然后在输入框里随意输入任意字符,就能看到count
被重置为0了。
这就是在组件内部定义组件的问题了,每次渲染,Count
都是一个新组件,内部的状态也会重新初始化,所以count
被重置为了0。
错误三:直接执行组件函数
function Input() { const [value, setValue] = useState('') return <input value={value} onChange={e => setValue(e.target.value)} />}function Test() { return ( <div> {Input()} </div> )}
Input()
这么调用函数运行起来好像没啥问题啊,那 Input()
和 <Input />
有啥区别呢?我们加一个按钮来控制这个输入框的显示和隐藏
function Input() { const [value, setValue] = useState('') return <input value={value} onChange={e => setValue(e.target.value)} />}function Test() { const [visible, setVisible] = useState(true) const toggleVisible = () => { setVisible(v => !v) } return ( <div> <button onClick={toggleVisible}>{visible ? 'hide input' : 'show input'}</button> {visible && Input()} </div> )}
点击「hide input」
ErrorRendered fewer hooks than expected. This may be caused by an accidental early return statement.
当我们直接执行组件函数时,等价于下面这段代码
Input()
在这里并不是一个组件,只是一个函数的封装。所以
const [value, setValue] = useState('')
就变成了 Test
组件的第二个Hook。而 visible
状态变化时,第二个Hook就可能执行,也可能不执行。这就违反了React Hook的要求,从而导致报错~
这就是 Input()
和 <Input />
的区别, <Input />
这种JSX的写法, 最终会转换成React.createElement
的函数调用,也就是创建一个组件,所以会有自己的state和hook。
结语
当你开始使用React时,可能会遇到一些错误和挑战。但是,只要你能够认真学习和理解React的工作原理,遵循React最佳实践,避免常见的错误,你就能够编写出高质量、高效的React代码。希望这篇文章能够帮助你避免React开发中常见的错误,让你的React应用更加稳定和可靠。不断学习和实践,相信你会成为一名出色的React开发者!