首页 > 解决方案 > 反应上下文没有更新

问题描述

我已经从嵌套道具切换到我的组件到 React 的 Context API。我创建了一个类来为我提供一些所需的方法:

export default class StepDatabase {
  private readonly steps: Steps = steps;
  private currentStep: number = steps[0].step;

  public getStep(): Step {
    return this.steps[this.currentStep];
  }

  public nextStep(): void {
    if (this.currentStep === this.steps.length) return;
    this.currentStep++;
  }
}

然后,创建了一个上下文:

const stepsInstance = new StepsDatabase();
export const StepsContext = createContext<StepsDatabase>(stepsInstance);

当然,然后提供它:

const App = () => (
    <div className={styles.App_container}>
      <main className={styles.App_grid}>
        <StepsContext.Provider value={stepsInstance}>
          <Sidebar />
          <Content />
        </StepsContext.Provider>
      </main>
    </div>
);

并尝试在我的Sidebar组件中使用它:

const Sidebar = () => {
  const StepContext = React.useContext(StepsContext);
  const currentStep = StepContext.getStep();

  return (
    <section className={`${styles.App_gridItem} ${styles.App_sideItem}`}>
      <SidebarHeading>{currentStep.stepName}</SidebarHeading>
      <SidebarParagraph>{currentStep.stepDescription}</SidebarParagraph>

      <button onClick={() => StepContext.nextStep()}>step</button>
    </section>
  );
};

但是在单击我的按钮后, SidebarHeadingandSidebarParagraph根本没有更新。第一步工作得很好。有什么问题?

标签: reactjsreact-context

解决方案


您的代码中没有任何内容会触发上下文重新呈现。如果上下文不重新渲染,它将无法触发所有使用它的组件。您需要更高级别的东西来导致上下文重新渲染,或者您需要将上下文中的函数传递给可能触发重新渲染的消费者。请参阅文档

这是基于您的代码的示例:

import React, { createContext, useState } from "react";
import "./styles.css";

const StepsContext = createContext();

const Sidebar = () => {
  const { step, setNextStep } = React.useContext(StepsContext);

  return (
    <section>
      <div>Heading: {step.stepName}</div>
      <div>Paragraph: {step.stepDescription}</div>

      <button onClick={() => setNextStep()}>step</button>
    </section>
  );
};

export default function App() {
  const [steps, setSteps] = useState([
    { stepName: "Step 1", stepDescription: "My description 1" },
    { stepName: "Step 2", stepDescription: "My description 2" }
  ]);
  const [currentStep, setCurrentStep] = useState(0);

  return (
    <div>
      <main>
        <StepsContext.Provider
          value={{
            step: steps[currentStep],
            setNextStep: function () {
              if (currentStep < steps.length - 1) {
                setCurrentStep(currentStep + 1);
              }
            }
          }}
        >
          <Sidebar />
          <div>Content</div>
        </StepsContext.Provider>
      </main>
    </div>
  );
}

推荐阅读