有没有办法使用 React Hooks API 来模拟构造函数代码的 运行 频率?

Is there a way to emulate the run frequency of constructor code using the React Hooks API?

有时,我发现在 React class 组件的 constructor 中放置一些代码很有用,可以进行一次处理(当组件被实例化时)并能够引用结果自始至终。现在有没有办法使用 React Hooks 对功能组件执行此操作 API?

示例:

constructor(props) {
    super(props);
    const componentFactory = createComponentFactory(props.context);
    this.components = props.components.map(componentFactory);

useEffect 可用于 运行 代码一次,但这发生在组件挂载上,因此它对应于 componentDidMount,而不是构造函数:

let components = useRef();

useEffect(() => {
  components.current = props.components.map(createComponentFactory(props.context))
}, []);
// components.current === null
// on first render

useMemo 可用于 运行 第一次渲染时的代码:

const components = useMemo(
  () => props.components.map(createComponentFactory(props.context)),
  []
);

不保证在未来的 React 版本中 运行 代码一次:

You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance.

useState 也可用于 运行 第一次渲染时的代码:

const [components] = useState(
  () => props.components.map(createComponentFactory(props.context))
);

由于其他选项的限制,最后一个选项可以被认为是更可取的方式。

您似乎需要实例变量之类的东西。

您可以使用 useRef() 钩子来做到这一点。

Docs: Hooks API

Essentially, useRef is like a “box” that can hold a mutable value in its .current property.

You might be familiar with refs primarily as a way to access the DOM. If you pass a ref object to React with , React will set its .current property to the corresponding DOM node whenever that node changes.

However, useRef() is useful for more than the ref attribute. It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes.

Docs: Hooks FAQ

Is there something like instance variables?

Yes! The useRef() Hook isn’t just for DOM refs. The “ref” object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class.