只有高级 React 工程师知道的事情

45 阅读2分钟

React 对于初学者来说可能很棘手。但是,了解一些基本原理或技巧可以使成为一名高级 React 工程师更容易。

1. useEffect 清理回调在每次渲染时执行

大多数人认为它仅在组件卸载时执行,但事实并非如此。

在每次渲染时,

上一个渲染的清理回调都会在下一个效果执行之前执行

让我们看一个例子:

function SomeComponent() {  const [count, setCount] = useState(0)  useEffect(() => {    console.log('The current count is ', count)    return () => {      console.log('The previous count is ', count)    }  })  return <button onClick={() => setCount(count + 1)}>Click me</button>}

这将记录以下内容:

// Component mountsThe current count is 0// ClickThe previous count is 0The current count is 1// ClickThe previous count is 1The current count is 2// Component unmountsThe previous count is 2

这对于创建 “unsubscribe then first subscribe” 模式很有用,这是 useEffect 唯一应该用于的事情。

当然,如果我们添加一个依赖数组,这些东西只有在依赖发生变化时才会被调用。

2. useEffect 是一个低级实用程序,应该只在类似库的代码中使用

初级 React 开发人员在不需要的时候使用 useEffect 是很常见的。这可能会使代码更加复杂、产生闪烁或细微的错误。

最常见的情况是同步不同的 useState,这时你实际上需要一个 useState:

function MyComponent() {  const [text, setText] = useState("Lorem ipsum dolor sit amet")  // You don't need to do this !!!  const [trimmedText, setTrimmedText] = useState("Lorem ip...")  useEffect(() => {    setTrimmedText(text.slice(0, 8) + '...')  }, [text])}function MyBetterComponent() {  const [text, setText] = useState("Lorem ipsum dolor sit amet")  // Do this instead:  // (each time text changes, the component will re-render so trimmedText  //  will be up-to-date)  const trimmedText = text.slice(0, 8) + '...'}

3. 使用 key 属性重置内部状态

当 prop 在元素上发生更改时,该元素的 render 不会被解释为更新,而是作为 unmount 加上具有 fresh state 的全新组件实例的 mount。

key

function Layout({ currentItem }) {  /* When currentItem changes, we want any useState inside <EditForm/>     to be reset to a new initial value corresponding to the new item */  return (    <EditForm      item={currentItem}      key={currentItem.id}    />  )}

4. 不要将服务器状态放在 useState 中

服务器状态或多或少是数据库的快照,在加载页面时,该快照位于前端的内存中。

通常它由服务器状态管理器管理,如 react-query 或 Apollo。

如果你将它中的任何一个放在 useState 中,当查询刷新或发生变化时,你的 useState 的内容将不会更新。

5. ReactElement 与 ReactNode

ReactElement

只表示一个标记,而可以是 React 可以渲染的任何东西,也可以是 、 等。

ReactNode``ReactElement``string``number``boolean``array``null``undefined

// this is a ReactElementconst a = <div/>// these are ReactNodes1"hello"<div/>[2, <span/>]null

始终按原样键入 prop,你不想限制该组件可以放置的子组件。

children``ReactNode

JSX.Element

是一个内部的 Typescript 功能(不是由 React 库定义的),仅针对库开发人员。除此之外,它等效于 .

ReactElement