简体   繁体   中英

How could i pass a value from a child component to parent, when i have multiple child components?

I creat multiple components, they have the same hierarchy, and inside they i also call other component call, now i want to create functions on my which will update the values i'm passing as props to my component. I manage to pass the functions as props, but can't manage to pass the value from child as parameters to the functions, so i could update only the props especific to that child.

App


function App() {
  // eslint-disable-next-line
  const [content, setContent] = useState(images)
  const [count, setCount] = useState(content.votes)

  console.log(count)

  const upVote = (id) => {
    alert('up =>', id)
  }

  const downVote = () => {
    alert('down')
  }

  return (
    <div className="App">
      <div className="grid">
        {content.map((picture, index) => {
          return <Card key={index} picture={picture} teste={[upVote, downVote]}/>
          })
        }
      </div>
    </div>
  )
}

Card

function Card({ picture, teste }) {

  return (
    <div className="card">
      <div className="container">
        <img
          width="300"
          alt={`id: ${picture.id}`}
          src={picture.src}
          className="image"
        />
        <Options votes={0} originalPost={picture.original_post} teste={teste[0]}/>
      </div>
    </div>
  )
}

Options

function Options({ votes, originalPost, teste }) {

  const [count, setCount] = useState(votes)
  const [styling, setStyling] = useState('#696969')

  function countStyle(count) {
    if (count > 0){
      setStyling('#008000')
    } else if (count < 0) {
      setStyling('#B22222')
    } else {
      setStyling('#696969')
    }
  }

  return (
    <div>
      <button onClick={() => teste(count)} className="buttons">teste</button>        
      <button title="Down vote" onClick={() => { 
        setCount(count - 1)
        countStyle(count-1)
        // style(count - 1)
      }} className="buttons">-</button>

      <span title="Vote counter" style={{color: styling}} className="counter">{count}</span>

      <button title="Up vote" onClick={() => {
        setCount(count + 1)
        // style(count + 1)
        countStyle(count +1)
      }} className="buttons">+</button><br></br>

      <a href={originalPost} 
        target="_blank"
        title="Click to check the original post"
        rel="noopener noreferrer"
        className="link">Original post</a>
    </div>
  )
}

I would start by consolidating your state into the App component. Save the votes on your content array on each picture object. Pass the upvote and downvote functions down to each children and call them from your button clicks. I would also calculate the styling based on the props, rather than use state.

App

function App() {
  let initialstate = images.map(image => {
    image.votes = 0;
    return image;
  });

  const [content, setContent] = useState(initialstate);

  const upVote = index => {
    setContent(content[index].votes + 1);
  };

  const downVote = index => {
    setContent(content[index].votes - 1);
  };

  return (
    <div className="App">
      <div className="grid">
        {content.map((picture, index) => {
          return <Card key={index} picture={picture} index={index} upVote={upVote} downVote={downVote} />;
        })}
      </div>
    </div>
  );
}

Card

function Card({ index, picture, ...props }) {
  const upVote = () => props.upVote(index);
  const downVote = () => props.downVote(index);

  return (
    <div className="card">
      <div className="container">
        <img
          width="300"
          alt={`id: ${picture.id}`}
          src={picture.src}
          className="image"
        />
        <Options votes={picture.votes} originalPost={picture.original_post} upVote={upVote} downVote={downVote}/>
      </div>
    </div>
  )

Options

function Options({ votes, originalPost, upVote, downVote }) {
  let styling = '#696969';

  if (count > 0) {
    styling = '#008000';
  } else if (count < 0) {
    styling = '#B22222';
  } else {
    styling = '#696969';
  }

  return (
    <div>
      <button title="Down vote" onClick={downVote} className="buttons">
        -
      </button>

      <span title="Vote counter" style={{ color: styling }} className="counter">
        {votes}
      </span>

      <button title="Up vote" onClick={upVote} className="buttons">
        +
      </button>
      <br></br>

      <a
        href={originalPost}
        target="_blank"
        title="Click to check the original post"
        rel="noopener noreferrer"
        className="link"
      >
        Original post
      </a>
    </div>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM