如何正确地将节点从ref传递到上下文?

时间:2019-08-20 11:57:57

标签: javascript reactjs react-hooks react-context react-ref

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

  1. 传递ref而不是ref.current。但是在用例中,我将被迫使用类似contextRef.current之类的东西来代替contextNode

  2. 在获取firstRender之后,使用状态(类似于ref.current)重新呈现组件。这似乎不是最佳选择。

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

CodeSandbox

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
);

2 个答案:

答案 0 :(得分:1)

与其传递在更改后不触发渲染的ref,不如使用保留该ref的状态。这样,您可以根据需要从子级更改Context,同时可以正确更新值。

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>
    );
};

答案 1 :(得分:1)

我对此一无所知,但是在第一个渲染中传递ref.current无效,但是如果仅通过ref,它将在第一个渲染中有效。

工作codesandbox在哪里。

我不认为这

  

然后是用例,我将不得不使用诸如contextRef.current之类的东西来代替contextNode。

将是一个问题,这将是一件好事,因为使用它时,您将知道所获得的是参考。

执行此操作

  

在获得参考电流后,使用状态(类似于firstRender)重新渲染组件。这似乎不是最佳选择。

仅因为不使用ref.current,这似乎不是一个好习惯。