Home > front end >  In react, how to pass states down as props?
In react, how to pass states down as props?

Time:07-31

This is a very noob question but I've been trying all day do implement this. Please help me out.
Sorry for the length, just tried to put out the whole thing I am struggling with

I am trying to build custom buttons and to do so, I created a component so I can create as many buttons that I want. For that I declared a state and passed down some information as props, which is as follows:

import React, {useState} from 'react'
import Button from '../components/Button'

function CustomButton() {

  const [clicked, setClicked] = useState(false)

  return (
    <div className='CustomButton'>
      <Navbar />
      <Button setClicked={setClicked} name="Button One" clicked={clicked}/>
      <Button setClicked={setClicked} name="Button Two" clicked={clicked}/>
      <Button setClicked={setClicked} name="Button Three" clicked={clicked}/>
    </div>
  )
}

export default CustomButton

As you can see, we passed the state and name of that button down. To render this Buttons, following component has been created:

import React from 'react'
import Modal from './Modal/Modal'

function Button({setClicked, name, clicked}) {
  return (
    <div>
        <button onClick={() => {setClicked(true)}}>{name}</button>
        {clicked && <Modal closeModal={setClicked} name={`You Clicked ${name}`} />}
    </div>
  )
}

export default Button

And lastly, when once a button is clicked, we want to perform some action. That action is to pop the Modal on a screen. And to do so, we created a Modal and passed down few props. Code for the same is as follows:

import React from 'react'

function Modal({closeModal, name}) {
  return (
    <div className='modal'>
        <div className='modalContainer'>
          <p>{name}</p>
            <div>
                <button onClick={() => {closeModal(false)}}>&times;</button>
            </div> 
        </div>
    </div>
   )
}

export default Modal

The expected result is for a Modal to pop with "You clicked button One", supposing we clicked oneexpected result something similar to this.

The actual result is that all three Modals pop up one above the other when any of the three buttons are passed. The result: Actual Result

I realize that I am passing the states wrong way. When any of the button is clicked all three get set to true. I simply don't realize how. Don't they create a method for each one?

Also, can you guys please teach me a better/understandable way to write clicked logic. Like maybe

if(clicked){
     <Modal closeModal={setClicked} name={`You Clicked ${name}`} />
}

CodePudding user response:

Because you bind all three buttons with one state, You need a state as array, with items equal to the number of buttons.

 const [clicked, setClicked] = useState([false, false, false])

  return (
    <div className='CustomButton'>
      <Navbar />
      {
         clicked.map((button, i) => {
             return <Button setClicked={setClicked} name="Button Three" clicked={clicked[i]} index={i}/>
         })
      }
    </div>
  )

Then in the button component.

function Button({setClicked, name, clicked, index}) {
return (
    <div>
        <button onClick={() => {setClicked(prev => prev.map((item, i) => {
     return i === index ? true : item
   }))}}>{name}</button>
        {clicked && <Modal closeModal={setClicked} name={`You Clicked ${name}`} />}
    </div>
  )
}

And the modal component.

function Modal({ closeModal, name, index }) {


 return (
    <div className="modal">
      <div className="modalContainer">
        <p>{name}</p>
        <div>
          <button
            onClick={() => {
              closeModal((prev) =>
                prev.map((item, i) => {
                  return i === index ? false : item;
                })
              );
            }}
          >
            &times;
          </button>
        </div>
      </div>
    </div>
  );
}

You can find a working example on this link.

https://codesandbox.io/s/old-wood-zgjno9

CodePudding user response:

You can implement multiple modals like this:

import { useState } from "react";

export default function App() {
  const [showModal1, setShowModal1] = useState(false);
  const [showModal2, setShowModal2] = useState(false);
  return (
    <div className="App">
      <button onClick={(e) => setShowModal1(true)}>Button 1</button>
      <button onClick={(e) => setShowModal2(true)}>Button 2</button>
      {showModal1 && (
        <Modal text="Modal 1" onClose={(e) => setShowModal1(false)} />
      )}
      {showModal2 && (
        <Modal text="Modal 2" onClose={(e) => setShowModal2(false)} />
      )}
    </div>
  );
}

const Modal = ({ text, onClose }) => {
  return (
    <div>
      {text}
      <button onClick={onClose}>Close</button>
    </div>
  );
};

Working example

  • Related