reactjs 如何让组件知道哪个上下文调用了该组件?

8yparm6h  于 2023-06-05  发布在  React
关注(0)|答案(3)|浏览(187)

假设我有一个组件和两个上下文。两个上下文都可以使用此组件。当context1使用它时,组件本身应该执行const context=useContext(Context1)。当context2使用它时,组件本身应该执行const context=useContext(Context2)。但是这个组件如何知道哪个上下文正在使用它并执行指令呢?
好的,我将给予一个简单的例子,但真实的情况比它更复杂,例如,Common被 Package 了很多次,两个组件看起来不同。
公共组件

export default function Common(){
  const context=useContext(/*one of the context*/);
  context.setData(newData);
  return (
     <div>{context.data}</div>
  )
}

组件1

export const Context1 = createContext({ data, setData });

export default function Component1() {
  <Context1.Provider value={{data, setData }}>
     <Common />
  </Context1.Provider>
}

组件2

export const Context2 = createContext({ data, setData  });

export default function Component2() {
  <Context2.Provider value={{data, setData }}>
     <Common />
  </Context2.Provider>
}
iecba09b

iecba09b1#

您可以尝试将一些键值存储在本地存储中,并从那里获取组件中的值。
就像context1中一样,只需添加一行

localStorage.setItem('currentcontext', 'context1');

在context2中

localStorage.setItem('currentcontext', 'context2');

现在,然后你的组件加载只是从clocalstorage中检索值

var current = localStorage.getItem('currentcontext');

然后你将有当前使用的上下文名称存储在当前命名变量中。
我试图回答的基础上,我来了多少得到你的问题,如果你面临任何其他问题做评论...

ni65a41a

ni65a41a2#

如果你有一个必须选择使用哪个上下文的组件,我认为你应该重新考虑你的设计。如果您能解释这两个上下文是什么以及组件对它们做了什么,那么帮助会容易得多,但您似乎不愿意详细说明。
有没有一个原因,你不能有一个单一的上下文,其 * 值 * 的变化,而不是完全独立的上下文?我想我永远不会知道了。
如果您坚持要有两个上下文并让组件在它们之间进行选择,那么您可以有一个上下文来指定要使用的上下文。

const Context1 = React.createContext("I'm context one!");
const Context2 = React.createContext("I'm context two!");

const WhichContext = React.createContext(Context1);

function MyComponent() {
  const which = React.useContext(WhichContext);
  const context = React.useContext(which);
  
  return (
    <div>{context}</div>
  );
}

function App () {
  return (
    <WhichContext.Provider value={Context2}>
      <MyComponent />
    </WhichContext.Provider>
  );
}

const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

<div id="app"></div>

你也可以把它作为一个 prop :

const Context1 = React.createContext("I'm context one!");
const Context2 = React.createContext("I'm context two!");

const WhichContext = React.createContext(Context1);

function MyComponent(props) {
  const context = React.useContext(props.context);
  
  return (
    <div>{context}</div>
  );
}

function App () {
  return (
      <MyComponent context={Context2} />
  );
}

const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

<div id="app"></div>
kkbh8khc

kkbh8khc3#

虽然我同意这样做的必要性可能是对React设计的误解,但不应该需要;虽然 ray 的答案看起来更“React方式”和优雅…我会给予另一个选择。
您可以在默认的Context值中添加一些标志或信息,以定义Context是否实际可用:

const Context1 = createContext({available: false})

const Component = () => {
   const context1 = useContext(Context1)
   console.log(context1.available)
   return <div />
}
<Component /> // <-- will print "false"
<Context1.Provider value={{available: true}}>
  <Component /> // <-- will print "true"
</Context1.Provider>

相关问题