【问题标题】:How to pass a value using `createContext` from parent to child's child component?如何使用`createContext`将值从父组件传递给子组件?
【发布时间】:2021-07-18 14:09:15
【问题描述】:

而不是将props从父级传递给child1(child2的父级)->到child2, 我想使用createContext 并使用useContext 接收值。
我尝试做的事情不正确,因为我收到了一个错误**'booleanContext' is not defined**。

如何传递createContext 状态/值?

App.js
CreatePass 是 SignUp 中的一个组件

  const [signUpFirst, setIfSignUp] = useState(true);
  const booleanContext = createContext(setIfSignUp);
  
 return (
    <booleanContext.Provider value={setIfSignUp}>

   <div>
     </Switch>
   <Route exact path='/signup'>
          <SignUp homePage={exitSignUpPage} setUserNumber={setUserID} />
        </Route>
        <Route exact path='/home'>
          <Home userIDNumber={userID} setIfSignUp={setIfSignUp} />
        </Route>
      <CreatPass /> 
      </Switch>
     </div>
    </booleanContext.Provider>
  );

SignUp.js

  render() {
    return (
      <div className='signUp-div'>
        <Header />
        <Router history={history}>
          <div className='form-div'>
            <Redirect to='/signup/mobile' />
            <Switch>
              <Route exact path='/signup/mobile' component={MobileNum} />
              <Route exact path='/signup/idnumber'>
                <IdentNumber setPersonalID={this.props.setUserNumber} />
              </Route>
              <Route exact path='/signup/password'>
                <CreatePass />
              </Route>
            </Switch>
          </div>
        </Router>
      </div>
    );
  }

CreatePass.js //'booleanContext' is not defined no-undef

const CreatePass = () => {
  const changeBooleanValue = useContext(booleanContext);

  const handleClickButton = () => {
      changeBooleanValue(true);
  };

  return (
    <div className='form-div'>
  <button onClick={handleClickButton}>Click</button>
    </div>
  );
};
export default CreatePass;

编辑 - 更新:

这个解决方案不好它的值和我上面做的一样,booleanContext 未定义 -

export const booleanContext = createContext(); // default value is undefiend
...
const App = () => 
     return(
     <booleanContext.Provider value={setIfSignUp}>
      <CreatPass />        
     </booleanContext.Provider>
      )
}
export default App;

很高兴得到解释

【问题讨论】:

    标签: reactjs react-hooks use-context createcontext


    【解决方案1】:

    对于上下文提供者和消费者,通常我会为它创建 1 个钩子,例如 useBoolean.tsx,它返回您可以放入父组件中的 BooleanProvider 组件和您可以在子组件中导入的 useBoolean 函数。

    基本上,任何全局函数都应将其所有子函数包装在其Provider 中。

    因此,如果您希望 &lt;CreatePass/&gt; 访问来自提供者的值,则它需要是其 Provider 的子代

    <BooleanProvider>
      <CreatePass/>
    </BooleanProvider>
    

    useBoolean.tsx 会有这样的东西

    // useBoolean.tsx
    const BooleanContext = createContext()
    
    export const BooleanProvider = ({ children }) => {
      const [signUpFirst, setIfSignUp] = useState(true)
    
      return (
        <BooleanContext.Provider value={{ signUpFirst, setIfSignUp }}>
          {children}
        </BooleanContext.Provider>
      )
    }
    
    export const useBoolean = () => {
      const context = useContext(BooleanContext)
      if (context === undefined) {
        throw new Error(`${useBoolean.name} must be within ${BooleanProvider.name}`)
      }
      return context
    }
    

    父组件将像往常一样

    // Parent component
    import { BooleanProvider } from 'hooks/useBoolean'
    
    const Parent = () => (
      <BooleanProvider>
        <Child1 />
      </BooleanProvider>
    )
    

    Child1 将拥有 Child2,而 Child2 将使用我们创建的 useBoolean 函数

    // Child1 component
    const Child1 = () => (
      <div>
        <Child2 />
      </div>
    )
    
    // Child2 component
    import { useBoolean } from 'hooks/useBoolean'
    
    const Child2 = () => {
      const { setIfSignUp } = useBoolean()
    
      return <div></div>
    }
    

    希望这有助于为您澄清一些事情。我只是想在这里解释一下我对使用 react context api 的理解以及我的做法。

    我尝试创建这样的钩子函数以简化代码管理 - 它有助于我理解此上下文直接使用钩子命名约定的作用。当Provider :D 中没有使用钩子函数时,它也会引发错误。干杯?!

    【讨论】:

    • 我认为const BooleanContext = createContext({})应该初始化为null而不是object。
    • 是的,没错。谢谢那个人..如果它是未定义/空的..那么抛出错误将在钩子中起作用..
    【解决方案2】:

    移动“const booleanContext = createContext(setIfSignUp);”在组件之外,您不想在每次渲染时更改上下文引用。也为其他组件导出它。

    export const booleanContext = createContext(); // default value is undefiend
    ...
    const App = () => ...
    
    export default App;
    

    然后在 CreatePass 中,你应该导入上下文(使用命名导出,所以导入是这样的:

    import { booleanContext } from '..somePath../App'
    

    现在应该可以了。

    编辑:

    按预期工作 https://codesandbox.io/s/createcontexttest-0qvvm?file=/src/App.js

    编辑 2

    <App>
      <CreatePass /> // there is value undefined
      <Context.Provider value={'something'}>
        <CreatePass /> // value is defined
        <SignUp>
           <CreatePass /> // also defined
        </SignUp>
      </Context.Provider>
      <div>
        <CreatePass /> // undefined
      </div>
    </App>
    

    【讨论】:

    • 我已经试过了,CreatePass undefined。 booleanContext / 我给它的名字 - changeBooleanValueundefined。不是一个好的解决方案。
    • 我在沙箱中尝试过(编辑中的链接),它按预期工作,也许尝试“调试器;”,如果所有值都通过了。
    • 您的 CodeSandbox 链接是一个空项目,请检查。
    • 那是因为CreatePass 不在SignUp 组件内。我在您的代码和框中更改了它并收到此错误 - changeBooleanValue is not a function。 App.js - return ( &lt;div className="App"&gt; &lt;h1&gt;Hello CodeSandbox, value: {"" + signUpFirst}&lt;/h1&gt; &lt;Switch&gt; &lt;Route&gt; &lt;SignUp /&gt; &lt;/Route&gt; &lt;/Switch&gt; &lt;booleanContext.Provider value={setIfSignUp}&gt; &lt;CreatePass /&gt; &lt;/booleanContext.Provider&gt; &lt;/div&gt; ); 并将 SignUp 组件固定为 Createpass 的父组件
    【解决方案3】:

    代码看起来不错。您可以修复导出带有空对象{} 的上下文时的默认值错误。

    export const booleanContext = createContext({}); 
    export default function App() {
        ...
        return (
         <booleanContext.Provider value={setIfSignUp}>
             ...
         </booleanContext.Provider>
        )
    }
     
    

    并导入它CreatePass.js

    import React, { useContext } from "react";
    import { booleanContext } from "./App";
    
    const CreatePass = () => {
         const changeBooleanValue = useContext(booleanContext);
         ...
    }
    

    【讨论】:

      【解决方案4】:

      首先,为您的上下文提供者创建一个自定义组件:

      import { createContext } from "react";
      
      const CustomContext = createContext(["green", () => {}]);
      
      export default CustomContext;
      

      然后在 App.js 中使用它来包装所有组件:

      <CustomContext.Provider value={options}>
        […]
      </CustomContext.Provider>
      

      然后你可以如下使用它:

      import CustomContext from "./CustomContext";
      
      // top of SearchParams function body
      const [options] = useContext(CustomContext);
      

      【讨论】:

      • 我试过了,但我在一个页面中获得了组件createPass,而不是其他组件,如果我忽略它(并在注册中传递所有过程),我会得到一个错误 - TypeError: changeBooleanValue is not a function.
      • 我的 App.js 中不需要自定义组件。因为 - const [signUpFirst, setIfSignUp] = useState(true); 在 App.js 中使用
      • 如果您的意思是const changeBooleanValue = useContext(booleanContext); 部分,绝对是错误的!你应该改用const [_, changeBooleanValue] = useContext(booleanContext);
      • 我不明白 - changeBooleanValue 是在 CreatePass 组件中选择给它的名称。你的代码示例不是我的。
      • 我只将 setState - setIfSignUp 与 Provider 一起传递,你看到了吗?
      猜你喜欢
      • 2020-02-04
      • 1970-01-01
      • 2020-03-30
      • 2018-05-01
      • 1970-01-01
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      相关资源
      最近更新 更多