React 负责在必要时渲染组件和 Hook,以优化用户体验。它是声明式的:你在组件的逻辑中告诉 React 要渲染什么,React 会找出最佳的方式将其显示给用户。
切勿直接调用组件函数
组件只能在 JSX 中使用。不要将其作为普通函数调用。React 应该调用它。
React 必须决定何时调用你的组件函数 在渲染期间。在 React 中,你使用 JSX 来实现这一点。
function BlogPost() {
return <Layout><Article /></Layout>; // ✅ Good: Only use components in JSX
}
function BlogPost() {
return <Layout>{Article()}</Layout>; // 🔴 Bad: Never call them directly
}
如果组件包含 Hook,当组件在循环中或有条件地直接调用时,很容易违反 Hook 规则。
让 React 编排渲染还可以带来许多好处
- 组件不仅仅是函数。React 可以使用 Hook 为它们添加诸如局部状态之类的功能,这些功能与树中组件的标识相关联。
- 组件类型参与协调。通过让 React 调用你的组件,你还可以告诉它更多关于树的概念结构的信息。例如,当你从渲染
<Feed>
切换到<Profile>
页面时,React 不会尝试重用它们。 - React 可以增强你的用户体验。例如,它可以让浏览器在组件调用之间执行一些工作,这样重新渲染大型组件树就不会阻塞主线程。
- 更好的调试体验。如果组件是库知道的头等公民,我们就可以在开发中构建丰富的开发者工具来进行自检。
- 更高效的协调。React 可以准确地确定树中哪些组件需要重新渲染,并跳过不需要重新渲染的组件。这使得你的应用程序更快、更流畅。
切勿将 Hook 作为普通值传递
Hook 只能在组件或 Hook 内部调用。切勿将其作为普通值传递。
Hook 允许你使用 React 功能来增强组件。它们应该始终作为函数调用,切勿作为普通值传递。这使得局部推理成为可能,或者开发人员能够通过孤立地查看组件来理解组件可以执行的所有操作。
违反此规则会导致 React 无法自动优化你的组件。
不要动态修改 Hook
Hook 应该尽可能“静态”。这意味着你不应该动态地修改它们。例如,这意味着你不应该编写高阶 Hook。
function ChatInput() {
const useDataWithLogging = withLogging(useData); // 🔴 Bad: don't write higher order Hooks
const data = useDataWithLogging();
}
Hook 应该是不可变的,并且不应该被修改。与其动态地修改 Hook,不如创建一个具有所需功能的 Hook 的静态版本。
function ChatInput() {
const data = useDataWithLogging(); // ✅ Good: Create a new version of the Hook
}
function useDataWithLogging() {
// ... Create a new version of the Hook and inline the logic here
}
不要动态使用 Hooks
也不应该动态地使用 Hooks:例如,不要通过将 Hook 作为值传递来在组件中进行依赖注入。
function ChatInput() {
return <Button useData={useDataWithLogging} /> // 🔴 Bad: don't pass Hooks as props
}
你应该始终将 Hook 的调用内联到该组件中,并在其中处理任何逻辑。
function ChatInput() {
return <Button />
}
function Button() {
const data = useDataWithLogging(); // ✅ Good: Use the Hook directly
}
function useDataWithLogging() {
// If there's any conditional logic to change the Hook's behavior, it should be inlined into
// the Hook
}
这样,<Button />
就更容易理解和调试。动态使用 Hooks 会大大增加应用程序的复杂性,并阻碍局部推理,从长远来看会降低团队的生产力。它还会更容易意外地违反Hooks 规则,即 Hooks 不应被有条件地调用。如果你发现需要为测试模拟组件,最好模拟服务器以响应预设数据。如果可能,通常使用端到端测试测试你的应用程序也更有效。