inzn
inzn

Reputation: 61

Pass true/false state from a child to the parent- React

I would like to change a true/false state in a child component and pass it to a parent component, where the state is actually defined. Right now, this results only in an error.

Parent:

const PostTemplate = ({ data }) => {
  const [isSlider, setIsSlider] = useState(false);

  return (
        <Layout class="page">
          <main>
                <Views setIsSlider={isSlider} {...data} />
          </main>
        </Layout>
      )}
    </>
  );
};

Child:

const Views = (data) => {
  return (
      <div
        key="views"
        className="post__gallery views"
      >
        {data.views.edges.map(({ node: view }) => (
          <divy
            onClick={() => setIsSlider(true)}
          >
            <GatsbyImage
              image={view.localFile.childImageSharp.gatsbyImageData}
            />
            <div
              className="post__caption"
              dangerouslySetInnerHTML={{
                __html: view.caption,
              }}
            />
          </div>
        ))}
      </div>
  );
};

Right now, this puts out:

setIsSlider is not a function.
(In 'setIsSlider(true)', 'setIsSlider' is false)

Perhaps also relevant the console.log from React:

Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

Upvotes: 0

Views: 1195

Answers (3)

李嘉伟
李嘉伟

Reputation: 21

To Fix: Change setIsSlider={isSlider} into setIsSlider={setIsSlider}.

However, in case you need to manage more than a few states across components. I would suggest using Redux. This can centralize your common-used states, you can access or update these states in any component using Redux.

Upvotes: 1

Uttam
Uttam

Reputation: 776

Instead of passing the state variable you have to pass the state function like this:

Parent

const PostTemplate = ({ data }) => {
  const [isSlider, setIsSlider] = useState(false);

  return (
        <Layout class="page">
          <main>
                <Views setIsSlider={setIsSlider} {...data} />
          </main>
        </Layout>
      )}
    </>
  );
};

Child

You've to use data.<function_passed_via_props> to access the setIsSlider function, like this:

const Views = (data) => {
  return (
      <div
        key="views"
        className="post__gallery views"
      >
        {data.views.edges.map(({ node: view }) => (
          <divy
            onClick={() => data.setIsSlider(true)}
          >
            <GatsbyImage
              image={view.localFile.childImageSharp.gatsbyImageData}
            />
            <div
              className="post__caption"
              dangerouslySetInnerHTML={{
                __html: view.caption,
              }}
            />
          </div>
        ))}
      </div>
  );
};

Upvotes: 2

Nick Bailey
Nick Bailey

Reputation: 3162

You're passing isSlider as a prop. You should be passing setIsSlider.

Note that state management in React is a complex topic and you probably want to do some research into how it is done in general. Directly passing a state setting callback works, but it doesn't scale well to complex applications.

Upvotes: 4

Related Questions