Reputation: 983
I've switched from nesting props to my components into React's Context API. I've created a class to serve me some desired methods:
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++;
}
}
And then, created a context:
const stepsInstance = new StepsDatabase();
export const StepsContext = createContext<StepsDatabase>(stepsInstance);
Of course, then provided it:
const App = () => (
<div className={styles.App_container}>
<main className={styles.App_grid}>
<StepsContext.Provider value={stepsInstance}>
<Sidebar />
<Content />
</StepsContext.Provider>
</main>
</div>
);
And tried using it in my Sidebar
component:
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>
);
};
But the SidebarHeading
and SidebarParagraph
wasn't updating at all after clicking my button. The first step has worked fine. What's the problem?
Upvotes: 0
Views: 268
Reputation: 2363
There is nothing in your code that triggers the context to re-render. If the context does not re-render, it won't be able to trigger all of the components that consume it. You need something at a higher level to cause the context to re-render, or you need to pass a function within your context to your consumers that may trigger the re-render. See the documentation.
Here is an example based upon your code:
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>
);
}
Upvotes: 3