React.createContext的defaultValue点?

时间:2018-04-20 20:13:58

标签: javascript reactjs

React 16 Context doc page上,他们的示例与此类似:

const defaultValue = 'light';
const SomeContext = React.createContext(defaultValue);

const startingValue = 'light';
const App = () => (
  <SomeContext.Provider theme={startingValue}>
    Content
  </SomeContext.Provider>
)

似乎defaultValue是无用的,因为如果您将startingValue设置为其他内容或者不设置它(undefined),它会覆盖它。没关系,应该这样做。

但那么defaultValue是什么意思?

如果我想要一个不会改变的静态上下文,那么能够执行以下操作会很好,只需让提供者通过defaultValue

const App = () => (
  <SomeContext.Provider>
    Content
  </SomeContext.Provider>
)

3 个答案:

答案 0 :(得分:10)

当没有Provider时,defaultValue参数用于函数createContext。这有助于单独测试组件而不包装它们,或者使用Provider中的不同值对其进行测试。

答案 1 :(得分:2)

我的两分钱

像往常一样阅读Kent C. Dodds的this instructive article :)之后,我了解到当您对useContext返回的值进行解构时,defaultValue很有用:

在没有defaultValue的情况下在代码库的一角定义上下文:

const CountStateContext = React.createContext() // <-- define the context in one corner of the codebase without defaultValue

并在组件中像这样使用它:

const { count } = React.useContext(CountStateContext)

JS显然会说TypeError: Cannot read property 'count' of undefined

但是您不能这样做,而完全避免使用defaultValue。

关于考试,我的老师肯特(Kent)说得很好:

React文档建议提供默认值“可能会有所帮助 隔离测试组件而不包装它们。” 是的,它允许您执行此操作,我不同意它比 用必要的上下文包装您的组件。请记住 每次您在测试中做某事而您在测试中不做 应用程序,可以降低测试可以给您的信心 你。

TypeScript的额外功能;如果您不想使用defaultValue,则可以通过以下操作轻松取毛:

const MyFancyContext = React.createContext<MyFancyType | undefined>(undefined)

您只需要确保稍后再添加额外的验证,以确保您已涵盖MyFancyContext === undefined的情况

  • MyFancyContext ?? “默认”
  • MyFancyContext?.notThatFancyProperty

答案 2 :(得分:0)

您可以使用 useReducer 钩子设置默认值,然后第二个参数将是默认值:

import React, { createContext, useReducer } from "react";
import { yourReducer } from "./yourReducer";

export const WidgetContext = createContext();

const ContextProvider = (props) => {

  const { children , defaultValues } = props;
 
  const [state, dispatch] = useReducer(yourReducer, defaultValues);

  return (
    <WidgetContext.Provider value={{ state, dispatch }}>
      {children}
    </WidgetContext.Provider>
  );
};

export default ContextProvider;

// 实现

   <ContextProvider
                  defaultValues={{
                    disabled: false,
                    icon: undefined,
                    text: "Hello",
                    badge: "100k",
                    styletype: "primary",
                    dir: "ltr",
                    }}
                >
    </ContextProvider>