在 React 中,是否可以在上下文中存储引用?

pet*_*ter 15 html reactjs

我需要在应用程序范围内全局访问 VideoElement,以便在 Safari 等浏览器上的用户事件上播放它,并且想知道将 VideoElement 存储在上下文中是否是实现此目的的最佳方法。我通过 redux 操作以编程方式播放我的视频,在 Safari 中这是不可能的,除非它通过用户触发的事件(如点击)播放过一次

是否可以在上下文中存储元素(ref)?然后 VideoElement 将在我想要播放视频的组件中呈现,然后其他组件也可以访问上下文并能够调用诸如usePlayVideo基于上下文状态的函数,将调用 videoElement.play( ) 如果这是第一次播放视频,或者调度 redux 操作以编程方式播放视频,否则

Kev*_*iao 12

可以将引用存储到上下文中!您首先需要创建一个上下文。然后,您需要将值传递给上下文提供者并使用 useRef 挂钩创建一个 ref 对象。之后,将 ref 传递到值中。

现在,您在上下文提供程序下的组件之间共享了一个 ref 对象,如果您想检索或传递新的 ref,您可以使用 useContext 钩子来处理它。

这是演示(codesandbox)。

这是示例代码。

import { createContext, useContext, useEffect, useRef, useState } from "react";
import "./styles.css";

const MyContext = createContext();

export const ContextStore = (props) => {
  const ref = useRef();
  return <MyContext.Provider value={ref}>{props.children}</MyContext.Provider>;
};

export default function App() {
  return (
    <>
      <ContextStore>
        <MyComponent />
        <MyComponent2 />
      </ContextStore>
    </>
  );
}

const MyComponent = () => {
  const myContext = useContext(MyContext);

  return (
    <div className="App" ref={myContext}>
      <h1>Hello MyComponent1</h1>
    </div>
  );
};

const MyComponent2 = () => {
  const myContext = useContext(MyContext);
  const [divRef, setDivRef] = useState();
  useEffect(() => {
    setDivRef(myContext);
  }, [myContext]);

  return (
    <div className="App">
      <h1>{divRef?.current && divRef.current.innerText}</h1>
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)

  • 在 React Docs 中,它说“useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数 (initialValue)。返回的对象将在组件的整个生命周期中持续存在。” 如果重新创建ContextStore,肯定会丢失ref,但示例中没有重新创建。问题是将 ref 存储在上下文中。ContextStore 将保留您的引用数据,无论它如何“重新渲染”。 (2认同)
  • 是的,只有当您将提供程序放在应用程序的根目录上(以便能够在需要的任何地方使用上下文)并且应该**仅使用一次**时,这才有效,但是您不能只包装需要的组件提供者,因为使用这种方法,每次使用提供者时,它将创建一个新的 Ref 对象,并且包装在提供者内的组件将接收一个新的空 ref 对象。[这是使用此方法失败的场景](https://codesandbox.io/s/pass-ref-to-context-forked-5rx3og?file=/src/App.js) (2认同)

Erf*_*ary 9

您可以使用这种方法:

VideoContext.js

import { createContext, createRef, useContext } from "react";

const VideoContext = createContext();
const videoRef = createRef();

export const VideoContextProvider = (props) => {
  return (
    <VideoContext.Provider value={videoRef}>
      {props.children}
    </VideoContext.Provider>
  );
};

export const useVideoContext = () => useContext(VideoContext);
Run Code Online (Sandbox Code Playgroud)

例如App.js

import { useState, useEffect } from "react";
import { useVideoContext, VideoContextProvider } from "./VideoContext";

const SomeComponent = () => {
  const videoRef = useVideoContext();

  return (
    <div ref={videoRef}>
      <h1>Hey</h1>
    </div>
  );
};

const SomeOtherComponent = () => {
  const [ref, setRef] = useState();
  const videoRef = useVideoContext();

  useEffect(() => {
    setRef(videoRef);
  }, [videoRef]);

  return (
    <div>
      <h1>{ref?.current?.innerText}</h1>
    </div>
  );
};

export default function App() {
  return (
    <>
      <VideoContextProvider>
        <SomeComponent />
      </VideoContextProvider>

      {/* ... */}

      {/* Some other component in another part of the tree */}
      <VideoContextProvider>
        <SomeOtherComponent />
      </VideoContextProvider>
    </>
  );
}

Run Code Online (Sandbox Code Playgroud)

代码沙箱


Bho*_*yar -4

不可以。无法在 context api 上使用 Ref。React ref 被认为是用在渲染元素上。

您正在寻找的是转发 ref,以便您可以在任何您想要的地方使用它们