处理嵌套上下文提供者

时间:2020-05-05 18:54:46

标签: javascript reactjs react-native react-hooks context-api

我的应用程序中有一些嵌套的上下文提供程序,像这样

export const LangContext = React.createContext("javascript");
export const FontContext = React.createContext("mono-space");
export const FontSizeContext = React.createContext("16px");

const Store = ({ children }) => {
  const [lang, setLang] = useState("javascript");
  const [font, setFont] = useState("mono-space");
  const [fontSize, setFontSize] = useState("16px");
  return (
      <LangContext.Provider value={[lang, setLang]}>
        <FontContext.Provider value={[font, setFont]}>
          <FontSizeContext.Provider value={[fontSize, setFontSize]}>
              {children}
          </FontSizeContext.Provider>
        </FontContext.Provider>
      </LangContext.Provider>
  );
};

我确定这是一个不好的做法,但是我不确定如何处理。我希望能够为所有上下文创建一个上下文提供程序。

2 个答案:

答案 0 :(得分:1)

您可以简单地使用单个提供程序并将所需的值作为对象传递:

export const StoreContext = React.createContext({});
const Store = ({ children }) => {
  const [lang, setLang] = useState("javascript");
  const [font, setFont] = useState("mono-space");
  const [fontSize, setFontSize] = useState("16px");
  return (
      <StoreContext.Provider value={{lang, setLang, font, setFont, fontSize, setFontSize}}>
              {children}
      </StoreContext.Provider>
  );
};

也可以不使用useState,而可以将上面的内容修改为使用useReducer,并使API更加简单:

const initialState= {
   lang: 'javascript',
   font: 'mono-space',
   fontSize: '16px',
}

const reducer = (state, action) => {
    switch (action.type) {
        case 'SET_LANG': return {...state, lang: action.payload}
        case 'SET_FONT': return {...state, font: action.payload}
        case 'SET_FONTSIZE': return {...state, fontSize: action.payload}
        default: return state;
    }
}
export const StoreContext = React.createContext({});
const Store = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
      <StoreContext.Provider value={[state, dispatch]}>
              {children}
      </StoreContext.Provider>
  );
};

,在孩子中,您可以像这样使用它:

const Child = () => {
    const [state, dispatch] = useContext(StoreContext);
    const handleChange = (size) => {
         dispatch({type: 'SET_FONTSIZE', payload: size})
    }
    ....
}

答案 1 :(得分:0)

我想很好,我也得到了许多Context。但这并不理想,而且应用程序的结构不佳。

我建议阅读Kent C. Dodds的Application State Management,其中讨论Context prop-drilling 的问题,然后再介绍points to a Youtube-video来解释组件组成,我认为这是一个很好的设计模式,从长远来看可能会导致需要更少的Context和更好的管理状态。

我还建议您阅读How to use React Context effectively