【问题标题】:Sharing state between React components在 React 组件之间共享状态
【发布时间】:2019-01-31 06:50:12
【问题描述】:

我有一个表格组件(父级),在表格的每一行中,还有一个基本上是图像按钮(子级)的组件。单击时,图像按钮会从其默认的三个垂直点 (https://png.icons8.com/windows/1600/menu-2.png) 切换为下载图标。三个垂直点图像有一个 onClick 监听器,将其切换到下载图标,下载图标有一个 onClick 监听器,用于下载表格行中的文件。每个图像按钮都有自己的状态(基于要显示的图像)。在表格组件中,我有一个包裹整个屏幕的 div。单击该 div 时(基本上,如果您单击图像之外的任何位置),我希望能够将表中的所有图像重置回三个点。我不确定如何实现这一点,因为有很多子组件,每个子组件都有自己的状态(因此我认为 redux 不会工作)。有没有办法与表格组件共享每个图像按钮的状态?

这是一些表格代码

<div className='shield' onClick={() => this.resetDownloads()}></div>
<table className='table table-striped'>
  <tbody>
    this.props.songs.data.map((song, index) => 
      <tr key={index}>
       <td>{song.name}</td>
       <td>{song.artist}</td>
       <td>{song.duration}</td>
       <td><ActionButton song={song}/></td>
      </tr>
  </tbody>
 </table>

这是一些 ActionButton 组件

class ActionButton extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            download: false
        };
        this.toggle = this.toggle.bind(this);
    }

    toggle(e) {
        e.stopPropagation();
        this.setState({
            download: !this.state.download
        });
    }

    render() {
      return this.state.download ? (
        <div>
          <img src={Download} width='15%' onClick={(e) => this.props.downloadSong(this.props.song, e)}></img>
        </div>
      )
      : (
        <div>
          <img src={Dots} width='15%' onClick={(e) => this.toggle(e)} className='image'></img>
        </div>
      )
    }
}

【问题讨论】:

  • 你能分享你的代码吗?
  • @Anas 添加了一些代码!
  • @Ramesh 我看过那个问题,它并不真正适用于我,因为我有很多子组件并且不能使用 redux 来管理所有子组件的状态是相互独立的。
  • 表格单元格中的图像只能具有下载状态或3点状态对吗?表中的行数是否事先知道?

标签: javascript reactjs


【解决方案1】:

这是你lift your state up 的地方。实际上,首先,您的ActionButton 组件中不需要状态。它应该是一个无状态组件。您可以将所有数据保存在父组件中。

假设歌曲数据中有一个id 属性。您可以在父组件中跟踪downloadState,并将这首歌的id 添加到此状态对象。然后您可以将此值传递给您的ActionComponent 并使用它。此外,您可以将所有功能保留在父组件中。

const songs = [
  { id: "1", name: "Always Blue", artist: "Chet Baker", duration: "07:33" },
  { id: "2", name: "Feeling Good", artist: "Nina Simone", duration: "02:58" },
  { id: "3", name: "So What", artist: "Miles Davis", duration: "09:23" },
]

class App extends React.Component {
  state = {
    downloadState: {},
  }
  
  toggle = ( e, id ) => {
    e.stopPropagation();
    this.setState( prevState => ({
      downloadState: { ...prevState.downloadState, [id]: !prevState.downloadState[id]}
    }))
  }

  downloadSong = ( e, song ) => {
    e.stopPropagation();
    alert( song.name );
  }

  resetDownloads = () => this.setState({ downloadState: {}});
  

  render() {
    return (
      <div onClick={this.resetDownloads}>
      <table>
        <tbody>
        {
          songs.map((song, index) => (
          <tr key={index}>
            <td>{song.name}</td>
            <td>{song.artist}</td>
            <td>{song.duration}</td>
            <td>
            <ActionButton
              toggle={this.toggle}
              song={song}
              downloadState={this.state.downloadState}
              downloadSong={this.downloadSong}
            />
            </td>
          </tr>
          ))
        }
        </tbody>
      </table>
      </div>
    )
  }
}

const ActionButton = props => {
  const { downloadState, downloadSong, song, toggle } = props;
  
  const handleToggle = e => toggle(e, song.id);
  const handleDownload = e => downloadSong( e, song );
  
  const renderImages = () => {
    let images = "";
    if ( downloadState[song.id] ) {
      images = <p onClick={handleDownload}>Download</p>;
    } else {
      images = <p onClick={handleToggle}>Dots</p>;
    }
    return images;
  }

  return (
    <div>{renderImages()}</div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
table, th, td {
    border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

如果没有任何id 属性,那么您可以使用索引设置相同的逻辑,但我认为每个数据都应该有一个id :) 也许可以代替使用索引,相同的逻辑可以用于歌曲名称,因为它们几乎是独一无二的。谁知道:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2019-02-18
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    相关资源
    最近更新 更多