如何在同一组件中使用 React useContext 来显示上下文中的数据

Ila*_*lan 6 javascript reactjs react-hooks

我正在创建一个反应向导组件,并希望使用 context\xd7\xa5 在父级和子级之间传递数据 \xd7\xa0

\n\n

因此,我创建了一个向导、上下文、提供程序和自定义挂钩,但问题是,如果我尝试在向导组件上使用上下文,它不会显示正确的信息

\n\n

(参见https://codesandbox.io/embed/wizardwitcontext-rfpui

\n\n

如何做到这一点,以便我可以依赖向导本身上下文中的数据,以便我可以将登录名转移到自定义挂钩?

\n\n

useWizard.js:

\n\n
import React, { useContext, useEffect } from "react";\nimport { WizardContext } from "./WizardContext";\n\nconst useWizard = () => {\n  const [state, setState] = useContext(WizardContext);\n\n  function setMaxSteps(maxSteps) {\n    setState(state => ({ ...state, maxSteps }));\n  }\n  function moveToStep(index) {\n    if (state.maxSteps && state.maxSteps > index) {\n      setState({ ...state, currentStep: index });\n      return index;\n    }\n    return state.currentStep;\n  }\n\n  function back() {\n    if (state.maxSteps) {\n      if (state.currentStep > 0) {\n        setState({ ...state, currentStep: state.currentStep - 1 });\n        window.scrollTo(0, 0);\n      }\n    }\n  }\n\n  //move back a step\n  function next() {\n    if (state.currentStep < state.maxSteps) {\n      setState({ ...state, currentStep: state.currentStep + 1 });\n      window.scrollTo(0, 0);\n    }\n  }\n\n  return {\n    setMaxSteps,\n    moveToStep,\n    back,\n    next,\n    maxSteps: state.maxSteps,\n    currentStep: state.currentStep,\n    state\n  };\n};\n\nexport default useWizard;\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

向导.jsx:

\n\n
const { state, currentStep, back, next, maxSteps, setMaxSteps } = useWizard();\n\nreturn (\n    <div className="wizard">\n      <WizardProvider\n        maxSteps={React.Children.count(props.children)}\n        currentStep={0}\n      >\n        {/* <div className="wizard__upper">\n          <ProgressIndicator currentIndex={selected} onChange={onClick}>\n            {steps}\n          </ProgressIndicator>\n\n          <Button id="wizardCloseBtn" kind="ghost" onClick={onClose}>\n            <Icon icon={iconHeaderClose} />\n          </Button>\n        </div> */}\n        <div className="wizard__separator" />\n        <div className="wizard__content">\n          {`in wizard: cur=${currentStep}, max=${maxSteps}`}\n          {/* {getContentAt(0)} */}\n          {stepContentWithProps}\n        </div>\n\n        {/* <div className="wizard__buttons">\n          {showBack && (\n            <Link id="back" onClick={back}>\n              back\n            </Link>\n          )}\n          {showNext && (\n            <button id="next" onClick={next} kind="secondary">\n              Next Step\n            </button>\n          )}\n        </div> */}\n      </WizardProvider>\n    </div>\n  );\n
Run Code Online (Sandbox Code Playgroud)\n\n

第2步:

\n\n
import React, { useState, useContext, useEffect } from "react";\nimport useWizard from "./useWizard";\n\nfunction Step2(props) {\n  const {\n    currentStep,\n    moveToStep,\n    maxSteps,\n    setMaxSteps,\n    next,\n    prev\n  } = useWizard();\n\n  return (\n    <div>\n      <p>Step 2</p>\n      {`in step2 (inner child of wizard): cur=${currentStep} see that cur !== cur from wizard above`}\n      <br />\n      <button onClick={() => moveToStep(1)}>\n        Click me to change current step\n      </button>\n    </div>\n  );\n}\n\nexport default Step2;\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

最终结果是:

\n\n
in wizard: cur=undefined, max=undefined\np1\n\nin index.js: cur=undefined\nStep 2\n\nin step2 (inner child of wizard): cur=0 see that cur !== cur from wizard above\n\n\n
Run Code Online (Sandbox Code Playgroud)\n

Den*_*ash 7

useContext在与以下级别相同的级别Context.Provider中调用:

function Wizard(props) {
  // useWizard calls useContext
  const { state, currentStep, back, next, maxSteps, setMaxSteps } = useWizard();

  return (
    <div className="wizard">
      <WizardProvider
        maxSteps={React.Children.count(props.children)}
        currentStep={0}
      >
        <div className="wizard__content">
          {`in wizard: cur=${currentStep}, max=${maxSteps}`}
        </div>
      </WizardProvider>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

你需要改变你的结构并呼唤useContext孩子们Provider

function Wizard(props) {
  // useWizard calls useContext
  const { state, currentStep, back, next, maxSteps, setMaxSteps } = useWizard();

  return (
//      v You trying to get Provider's value here
    <div className="wizard">
      <WizardProvider
        maxSteps={React.Children.count(props.children)}
        currentStep={0}
      >
//      v useContext available within the children
        <ComponentA />
        <ComponentB />
      </WizardProvider>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

请参阅上下文 APIuseContext


Nit*_*mpi 0

上下文源自组件树上方最近的提供者。来自反应文档。

const 值 = useContext(MyContext);

接受上下文对象(从 React.createContext 返回的值)并返回该上下文的当前上下文值。当前上下文值由树中调用组件上方最近的值 prop 确定。

在这种情况下,您有 2 个选择。

1.您需要将您的App(index.js)组件包装在提供程序中。

或者

2.让Wizard组件成为提供者,并尝试在子组件中使用useContext钩子。

演示: https: //stackblitz.com/edit/react-msac8q

希望这可以帮助