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

jchrr9hc  于 2023-02-22  发布在  React
关注(0)|答案(5)|浏览(317)

我需要在应用程序范围内全局访问VideoElement,以便在Safari等浏览器上的用户事件中播放它,我想知道将VideoElement存储在上下文中是否是最好的方法。我通过redux操作以编程方式播放我的视频,在Safari中,除非通过用户触发的事件(如单击)播放过一次,否则这是不可能的。
是否可以将元素(ref)存储在上下文中?VideoElement将在我希望拥有视频的组件中呈现,然后其他组件也可以访问上下文,并能够基于上下文的状态调用usePlayVideo等函数,videoElement.play如果是第一次播放视频,则调用www.example.com(),或者分派redux动作以另外编程地播放视频

mrphzbgm

mrphzbgm1#

可以将ref存储到context中!首先需要创建一个context,然后将value传递给context提供者,使用useRef钩子创建一个ref对象,然后将ref传递给value。
现在,您有了一个在上下文提供者下的组件之间共享的ref对象,如果您想检索或传递一个新的ref,您可以使用useContext钩子来处理它。
下面是demo(代码和框)。
下面是示例代码。

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

gg58donl2#

您可以使用以下方法:
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);

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

code sandbox

3zwtqj6y

3zwtqj6y3#

为什么不呢?我也这么觉得。看看能不能树立一个榜样。

const fns = {}
const addDispatch = (name, fn) => { fns[name] = fn }
const dispatch = (name) => { fns[name] && fns[name]() }
const RefContext = createContext({ addDispatch, dispatch })
export default RefContext
const Child1 = () => {
  const [video, dispatchVideo] = useState(...)
  const { addDispatch } = useContext(RefContext)
  useEffect(() => {
    addDispatch('video', dispatchVideo)
  }, [])
}

const Child2 = () => {
  const { dispatch } = useContext(RefContext)
  const onClick = () => { dispatch('video') }
  ...
}

上述两个孩子不必共享同一祖先。
我没有用你想要的方式引用,但我认为你可以把你的引用传递给其中一个函数。这是一个非常基本的想法。我还没有测试它。但似乎它可以工作。一点点

vmdwslir

vmdwslir4#

我使用了以下方法:
首先创建了上下文和ContextProvider;

import React, { useRef } from "react";

export const ScrollContext = React.createContext();

const ScrollContextProvider = (props) => {
  return (
    <ScrollContext.Provider
      value={{
        productsRef: useRef(),
      }}
    >
      {props.children}
    </ScrollContext.Provider>
  );
};

export default ScrollContextProvider;

然后在我的index.js中添加我的提供程序:

root.render(
  <React.StrictMode>
    <ScrollContextProvider>
      <App />
    </ScrollContextProvider>
  </React.StrictMode>
);

在那之后,我在我需要的地方使用了我的上下文:

import React, { useContext } from "react";
import { ScrollContext } from "../../store/scroll-context";

const Products = () => {
  const scrollCtx = useContext(ScrollContext);

  return (
    <section ref={scrollCtx.productsRef}>
      // your code...
    </section>
  );
};

在我的例子中,我想滚动到上面的组件,单击另一个组件中的按钮:

import React, { useContext } from "react";
import { ScrollContext } from "../../store/scroll-context";

function Header() {
  const scrollCtx = useContext(ScrollContext);

  const scrollTo = () => {
    setTimeout(() => {
      scrollCtx.productsRef.current.scrollIntoView({ behavior: "smooth" });
    }, 0);
  };

  return (
    <header>
      //your code ...
      <button alt="A table with chair" onClick={scrollTo}>Order Now<button />
    </header>
  );
}
4szc88ey

4szc88ey5#

不可以。不能在上下文API上使用Ref。React ref被认为是在呈现元素上使用的。
您要寻找的是forward the ref,这样您就可以在任何需要的地方执行consume them

相关问题