Katharina Schreiber
Katharina Schreiber

Reputation: 1371

State change onClick with React Context

I am using a React Context to manage my States, but I am super new to the whole React universe. I have a Next.js App. My Context file:

import { useState, createContext, useContext } from "react";

export const QuizContext = createContext();

export default function QuizProvider({ children }) {
  const [data, setData] = useState({});
  const [isSelected, setisSelected] = useState();

  const setQuizValues = (values) => {
    setData((prevValues) => ({
      ...prevValues,
      ...values,
    }));
  };

  return (
    <QuizContext.Provider value={{ data, isSelected, setisSelected, setQuizValues }}>
      {children}
    </QuizContext.Provider>
  );
}

export const useQuizData = () => useContext(QuizContext);

You see, I also use Context to manage a multistep form, but please ignore this in the code for now. What is not working, is passing setisSelected to my Card component. In the file, where I render several Cards I try to select a Card, using Context. This is just part of my code. All works, except for setisSelected.

export const TacoCathegories = ({quizStep, prevQuizStep, nextQuizStep}) => {
  const { setQuizValues } = useQuizData();
  const quizData = useContext(QuizContext);
  const selectedCard = quizData.isSelected;


  const handleSubmit = (values) => {
    setQuizValues(values);
    prevQuizStep();
    nextQuizStep();
  };

  return (
    <div className={quizStep === 0 ? 'block': 'hidden'}>
      <div className="text-center">
        <h2 className="text-3xl font-extrabold tracking-tight text-gray-600 sm:text-4xl">What is your favourite taco group?</h2>
      </div>
      <div className="max-w-7xl mx-auto py-24 px-4 sm:px-6 lg:px-8">
        <div className="mt space-y-12 lg:space-y-0 lg:grid lg:grid-cols-3 lg:gap-x-8">
          {tacos.map((taco, index) => (
            <Card 
            role="button"
            key={index}
            title={taco.cathegory}
            source={taco.imgURL}
            text={`image of ${taco.cathegory} `}
            selected={selectedCard === index}
            onChange={() => setisSelected(index)}
            />
            
          ))}
        </div>
        {tacos[selectedCard] && <p>{tacos[selectedCard].cathegory}</p>}
        
        <div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-center">
          <div className="rounded-md shadow">
            <a role="button" tabIndex={0}
              className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-gray-200 hover:bg-gray-200 focus:outline-none md:py-4 md:text-lg md:px-10 cursor-not-allowed"
            >
              Back
            </a>
          </div>
          <div className="mt-3 sm:mt-0 sm:ml-3">
            <a
              onClick={nextQuizStep}
              className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-yellow-500 hover:bg-yallow-600 md:py-4 md:text-lg md:px-10"
            >
              Next
            </a>
          </div>
        </div>
      </div>
    </div>
  );
}

I get an Error ReferenceError: setisSelected is not defined. If I do this without the Context, directly in the component, it works. So I assume, I am somehow not passing setisSelected right.

Upvotes: 0

Views: 1639

Answers (1)

Mohaimin
Mohaimin

Reputation: 702

You have not extracted the setisSelected from the Context so it's undefined.

 const quizData = useContext(QuizContext);
 const selectedCard = quizData.isSelected;
 const setisSelected = quizData.setisSelected ; // add this

Also you can leverage Object Destructuring to get all the properties in one line from the context

const { selectedCard, setisSelected  } = useContext(QuizContext);

Upvotes: 1

Related Questions