首页 > 解决方案 > 如何在同一个组件中使用 react useContext 来显示上下文中的数据

问题描述

我正在创建一个反应向导组件,并希望使用上下文在父母和孩子之间传递数据

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

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

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

使用向导.js:

import React, { useContext, useEffect } from "react";
import { WizardContext } from "./WizardContext";

const useWizard = () => {
  const [state, setState] = useContext(WizardContext);

  function setMaxSteps(maxSteps) {
    setState(state => ({ ...state, maxSteps }));
  }
  function moveToStep(index) {
    if (state.maxSteps && state.maxSteps > index) {
      setState({ ...state, currentStep: index });
      return index;
    }
    return state.currentStep;
  }

  function back() {
    if (state.maxSteps) {
      if (state.currentStep > 0) {
        setState({ ...state, currentStep: state.currentStep - 1 });
        window.scrollTo(0, 0);
      }
    }
  }

  //move back a step
  function next() {
    if (state.currentStep < state.maxSteps) {
      setState({ ...state, currentStep: state.currentStep + 1 });
      window.scrollTo(0, 0);
    }
  }

  return {
    setMaxSteps,
    moveToStep,
    back,
    next,
    maxSteps: state.maxSteps,
    currentStep: state.currentStep,
    state
  };
};

export default useWizard;

向导.jsx:

const { state, currentStep, back, next, maxSteps, setMaxSteps } = useWizard();

return (
    <div className="wizard">
      <WizardProvider
        maxSteps={React.Children.count(props.children)}
        currentStep={0}
      >
        {/* <div className="wizard__upper">
          <ProgressIndicator currentIndex={selected} onChange={onClick}>
            {steps}
          </ProgressIndicator>

          <Button id="wizardCloseBtn" kind="ghost" onClick={onClose}>
            <Icon icon={iconHeaderClose} />
          </Button>
        </div> */}
        <div className="wizard__separator" />
        <div className="wizard__content">
          {`in wizard: cur=${currentStep}, max=${maxSteps}`}
          {/* {getContentAt(0)} */}
          {stepContentWithProps}
        </div>

        {/* <div className="wizard__buttons">
          {showBack && (
            <Link id="back" onClick={back}>
              back
            </Link>
          )}
          {showNext && (
            <button id="next" onClick={next} kind="secondary">
              Next Step
            </button>
          )}
        </div> */}
      </WizardProvider>
    </div>
  );

第2步:

import React, { useState, useContext, useEffect } from "react";
import useWizard from "./useWizard";

function Step2(props) {
  const {
    currentStep,
    moveToStep,
    maxSteps,
    setMaxSteps,
    next,
    prev
  } = useWizard();

  return (
    <div>
      <p>Step 2</p>
      {`in step2 (inner child of wizard): cur=${currentStep} see that cur !== cur from wizard above`}
      <br />
      <button onClick={() => moveToStep(1)}>
        Click me to change current step
      </button>
    </div>
  );
}

export default Step2;

最终结果是:

in wizard: cur=undefined, max=undefined
p1

in index.js: cur=undefined
Step 2

in step2 (inner child of wizard): cur=0 see that cur !== cur from wizard above


标签: javascriptreactjsreact-hooks

解决方案


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>
  );
}

你需要改变你的结构并useContextProvider孩子们内部打电话。

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>
  );
}

请参阅上下文 API,。useContext


推荐阅读