React中使用BOM API的最佳实践及纯组件判定与改造咨询
嘿,这个问题问得特别接地气!咱们一步步来理清楚~
首先直接给结论:你写的这个Hello组件不是纯组件。
React对纯组件/纯函数组件的核心要求是:只要传入的props、组件自身的state,以及上下文(context)完全相同,组件就必须渲染出完全一致的内容,而且不能在渲染过程中依赖或修改任何外部的可变值。
你这里直接在组件里读取location.search,这就违反了纯组件的规则——哪怕组件的props、state、context都没变化,只要浏览器URL里的query参数改了,组件的输出就会不一样。这种直接依赖外部BOM环境的做法,会让组件的渲染结果脱离React的控制体系,也不符合纯组件的定义。
那怎么把它改成纯组件呢?有两种常用的靠谱方案:
方案一:把外部依赖转为props传入
核心思路是把读取BOM的逻辑移到组件外部,把需要的值通过props传递给目标组件,让组件的输出完全由props决定:
// 在父组件/路由入口组件中处理BOM读取逻辑 const ParentComponent = () => { const name = new URLSearchParams(location.search).get('name'); return <Hello name={name} />; } // 改造后的纯Hello组件 const Hello = ({ name }) => { return <div>hello, {name}</div>; }
现在这个Hello组件就完全符合纯组件的要求了——只要name props不变,它的输出就不会变,而且没有任何外部依赖。
方案二:用React生态的工具管理外部状态(比如React Router)
如果你是在React Router的项目里,可以用它提供的useSearchParams钩子,它会把URL的query参数封装成React可感知的状态,自动帮你处理BOM的变化:
import { useSearchParams } from 'react-router-dom'; const Hello = () => { const [searchParams] = useSearchParams(); const name = searchParams.get('name'); return <div>hello, {name}</div>; }
这个方案里,组件依赖的是React Router提供的状态(由useSearchParams返回),而不是直接读取BOM的location。当URL的query变化时,React会感知到状态更新并触发组件重新渲染,组件的输出依然由React管理的状态决定,也满足纯组件的核心要求。
最后补充一点:纯组件的好处不止是符合React的设计理念,还能让测试变得更简单——你只需要传入不同的props就能验证组件的输出,不用额外去模拟BOM环境;而且在React的严格模式下,纯组件的重复渲染也不会带来任何副作用。
备注:内容来源于stack exchange,提问作者fightant1w1ll

