12

我正在尝试将节点从 ref 传递到上下文。但是因为我在第一次渲染后没有重新渲染,所以传递的节​​点是null. 我考虑了两种变体(但我认为它们不是最好的):

  1. 通过ref而不是ref.current. 但是在用例中,我将被迫使用类似的东西contextRef.current而不是contextNode.

  2. firstRender获得ref.current. 这似乎不是最优的。

什么是正确的(最好的?)方法?

代码沙盒

import React, { createContext, createRef, useContext, useEffect } from "react";
import ReactDOM from "react-dom";

const Context = createContext(null);

const App = ({ children }) => {
  const ref = createRef();

  return (
    <div ref={ref}>
      <Context.Provider value={ref.current}>{children}</Context.Provider>
    </div>
  );
};

const Child = () => {
  const contextNode = useContext(Context);

  useEffect(() => {
    console.log(contextNode);
  });

  return <div />;
};

const rootElement = document.getElementById("root");
ReactDOM.render(
  <App>
    <Child />
  </App>,
  rootElement
);
4

2 回答 2

4

不要传递更改时不会触发渲染的 ref,而是使用保存 ref 的状态。这样,如果需要,您可以从孩子更改上下文,同时您可以正确更新值。

const App = ({ children }) => {
    const ref = useRef(null);
    const [ref_state, setRefState] = useState(null);

    useEffect(() => {
        if (!ref.current) {
            return;
        }

        setRefState(ref.current)
    }, []);

    return (
        <div ref={ref_state}>
            <Context.Provider value={ref.current}>{children}</Context.Provider>
        </div>
    );
};

如果您需要初始渲染指向元素,您可以(以非最佳方式)将初始值设置为 HTML 元素:

const App = ({ children }) => {
    const ref = useRef(document.querySelector("#app"));

    return (
        <div id="app" ref={ref}>
            <Context.Provider value={ref.current}>{children}</Context.Provider>
        </div>
    );
};
于 2019-08-20T12:12:44.143 回答
2

我不知道,但是ref.currentpass 在第一次渲染中不起作用,但是如果您只 pass ref,它将在第一次渲染中起作用。

工作代码和框在哪里

我不认为这

然后是用例,我将被迫使用 contextRef.current 之类的东西而不是 contextNode。

会是个问题,会很好,因为当使用它时,你会知道你得到的是一个 ref。

还,

做这个

在获得 ref.current 后,使用状态(类似于 firstRender)重新渲染组件。这似乎不是最优的。

只是因为不使用ref.current,看起来不是一个好习惯。

于 2019-08-20T12:14:19.393 回答