Reactjs 对多种情况作出反应

Reactjs 对多种情况作出反应,reactjs,Reactjs,我正在使用通过上下文传递的函数 ChildComponent.contextType = SomeContext; 现在我使用this.context.someFunction()。这很有效 如果我需要来自两个不同父组件的函数,如何执行此操作?您仍然可以在16.3上下文API中使用函数作为子使用者节点,这就是: 或者,如果您大量使用这些上下文,您甚至可以制作一个自定义挂钩来进一步简化: const useTheme = () => useContext(ThemeContext) con

我正在使用通过上下文传递的函数

ChildComponent.contextType = SomeContext;
现在我使用
this.context.someFunction()。这很有效


如果我需要来自两个不同父组件的函数,如何执行此操作?

您仍然可以在16.3上下文API中使用函数作为子使用者节点,这就是:

或者,如果您大量使用这些上下文,您甚至可以制作一个自定义挂钩来进一步简化:

const useTheme = () => useContext(ThemeContext)
const useUser = () => useContext(UserContext)

const YourComponent = props => {
  const theme = useTheme()
  const user = useUser()
}

您也可以简单地将所有上下文合并为一个上下文:

const AppContext = React.createContext({
  user: { name: 'Guest' },
  theme: 'light',
})

ChildComponent.contextType = AppContext;

完成了。如果应用程序的某些部分有不同的上下文(如不同的主题或用户),则只需合并新值。

另一种解决方案是创建一个单独的上下文,提供其他上下文:

import React, { createContext, memo, useContext } from "react";
import isEqual from "react-fast-compare";

export const MultiContext = createContext(null);
MultiContext.displayName = "MultiContext";

export const MultiContextProvider = memo(
  function({ map, children }) {
    const contextMap = {};
    for (const i in map) {
      contextMap[i] = useContext(map[i]);
    }

    return (
      <MultiContext.Provider value={contextMap}>
        {children}
      </MultiContext.Provider>
    );
  },
  (prevProps, nextProps) => isEqual(prevProps.children, nextProps.children)
);

MultiContextProvider.displayName = "MultiContextProvider";
import React,{createContext,memo,useContext}来自“React”;
从“快速反应比较”中导入isEqual;
export const MultiContext=createContext(null);
MultiContext.displayName=“MultiContext”;
导出常量MultiContextProvider=memo(
函数({map,children}){
const contextMap={};
用于(地图中的常数i){
contextMap[i]=useContext(map[i]);
}
返回(
{儿童}
);
},
(prevProps,nextProps)=>isEqual(prevProps.children,nextProps.children)
);
MultiContextProvider.displayName=“MultiContextProvider”;
用法示例:

class DemoConsumer extends React.Component {
  static contextType = MultiContext;

  render() {
    return JSON.stringify({
      someValue: this.context.SomeContext.someValue,
      otherValue: this.context.OtherContext.otherValue,
    });
  }
}

function App() {
  return (
    <MultiContextProvider map={{ SomeContext, OtherContext }}>
      <MultiContextDemoClassConsumer />
    </MultiContextProvider>
  );
}
类DemoConsumer扩展React.Component{
静态上下文类型=多上下文;
render(){
返回JSON.stringify({
someValue:this.context.SomeContext.someValue,
otherValue:this.context.OtherContext.otherValue,
});
}
}
函数App(){
返回(
);
}

演示:

const{
createContext,
备忘录,
使用上下文,
useState,
使用效果,
}=反应;
const MultiContext=createContext(null);
MultiContext.displayName=“MultiContext”;
const multicntextprovider=memo(
函数({map,children}){
console.log(“呈现提供程序”);
const contextMap={};
用于(地图中的常数i){
contextMap[i]=useContext(map[i]);
}
返回(
{儿童}
);
},
(prevProps,nextProps)=>isEqual(prevProps.children,nextProps.children)
);
MultiContextProvider.displayName=“MultiContextProvider”;
const initialMinutes=新日期().getMinutes();
const MinutesContext=createContext(initialMinutes);
MinutesContext.displayName=“MinutesContext”;
const IncrementContext=createContext(0);
IncrementContext.displayName=“IncrementContext”;
类MultiContextDemoClassConsumer扩展React.Component{
静态上下文类型=多上下文;
render(){
返回JSON.stringify(this.context);
}
}
常量multiContextMap={minuteContext,IncrementContext};
函数App(){
const forceUpdate=useForceUpdate();
const[minutes,setMinutes]=使用状态(initialMinutes);
useffect(()=>{
const timeoutId=setInterval(()=>{
//console.log('set minutes')
setMinutes(新日期().getMinutes());
}, 1000);
return()=>{
清除间隔(超时ID);
};
},[setMinutes]);
const[increment,setIncrement]=useState(0);
console.log(“渲染应用程序”);
返回(
setIncrement(i=>i+1)}>Increment
部队更新
);
}
render(,document.getElementById(“根”))

导入从'https://dev.jspm.io/react@16';
从'https://dev.jspm.io/react-dom@16';
从导入useForceUpdate'https://dev.jspm.io/use-force-update@1.0.7';
从'https://dev.jspm.io/react-fast-compare@3.0.1';
window.React=反应;
window.ReactDOM=ReactDOM;
window.useForceUpdate=useForceUpdate.default;
window.isEqual=isEqual;

上下文为我提供了在类中使用的函数,而不是要呈现的数据。@ATOzTOA这在多个上下文提供程序中的效果与正常情况相同,但我用一个简单的示例更新了我的答案。当
您的组件
是一个类时,
themeContext
变成
This.props.themeContext
,对吗?如果我真的需要将这些上下文彼此分离,我也会使用这种方法。我特别喜欢使用
和secondext
HOC:)重新考虑您的解决方案。当某些嵌套对象中的上下文值更改时,它会进行额外的重新渲染,不是吗?用户和主题都可以有嵌套对象,并且在更改对象后(即使不需要),它会导致到处重新渲染,除非我弄错了。请纠正我的错误wrong@sunpietro如果上下文的值更改,则任何使用上下文的组件都将重新渲染,是。这就是为什么在树的顶部有一个不经常变化的上下文,而在使用它的地方有一个变化很大的上下文是有意义的。你的解决方案很好,但为了避免渲染过度,我们可以使用useReducer钩子创建一个上下文。@HoussemBadri也许你可以发布一个答案来说明你的建议?
const AppContext = React.createContext({
  user: { name: 'Guest' },
  theme: 'light',
})

ChildComponent.contextType = AppContext;
import React, { createContext, memo, useContext } from "react";
import isEqual from "react-fast-compare";

export const MultiContext = createContext(null);
MultiContext.displayName = "MultiContext";

export const MultiContextProvider = memo(
  function({ map, children }) {
    const contextMap = {};
    for (const i in map) {
      contextMap[i] = useContext(map[i]);
    }

    return (
      <MultiContext.Provider value={contextMap}>
        {children}
      </MultiContext.Provider>
    );
  },
  (prevProps, nextProps) => isEqual(prevProps.children, nextProps.children)
);

MultiContextProvider.displayName = "MultiContextProvider";
class DemoConsumer extends React.Component {
  static contextType = MultiContext;

  render() {
    return JSON.stringify({
      someValue: this.context.SomeContext.someValue,
      otherValue: this.context.OtherContext.otherValue,
    });
  }
}

function App() {
  return (
    <MultiContextProvider map={{ SomeContext, OtherContext }}>
      <MultiContextDemoClassConsumer />
    </MultiContextProvider>
  );
}