首页 > 解决方案 > 当我有多个子组件时,如何将值从子组件传递给父组件?

问题描述

我创建了多个组件,它们具有相同的层次结构,并且在它们内部我还调用其他组件调用,现在我想在我的组件上创建函数,它将更新我作为道具传递给我的组件的值。我设法将函数作为道具传递,但无法将孩子的值作为参数传递给函数,因此我只能更新特定于该孩子的道具。

应用程序


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>
  )
}

卡片

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>
  )
}

选项

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>
  )
}

标签: javascriptreactjsreact-hooks

解决方案


我首先将您的状态整合到 App 组件中。将投票保存在每个图片对象的内容数组上。将 upvote 和 downvote 功能传递给每个孩子,并通过您的按钮点击调用他们。我还会根据道具计算样式,而不是使用状态。

应用程序

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>
  );
}

卡片

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>
  )

选项

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>
  );
}

推荐阅读