如何在不同的ReactJS组件实例中包含不同的数据?

时间:2017-12-05 11:56:29

标签: javascript reactjs redux

我们说我有2 <Logs/>个组件。它们仅在点击其父<Block/>时显示。每个<Block/>只有一个<Logs/>,但页面上会有很多<Blocks/>

class Block extends React.Component {

    toggleExpanded() {

        this.setState({
            isExpanded: !this.state.isExpanded
        });

    }

    render() {

        let blockId = // ...

        return (
            <div>
                <button type="button" onClick={() => this.toggleExpanded()}>Toggle</button>
                {this.state.isExpanded && <Logs blockId={blockId} />}
            </div>
        );

    }

}

export default Block;

创建<Logs/>后,我想使用Redux从服务器获取数据。有一天可能会有很多<Logs/>因此我不想加载所有数据,只需要根据需要加载数据。

class Logs extends React.Component {

    componentDidMount() {

        if (!this.props.logs) {
            this.props.fetchBlockLogs(this.props.blockId);
        }

    }

    render() {

        return (this.props.logs && this.props.logs.length)
            ? (
                <ul>
                    {this.props.logs.map((log, i) => <li key={i}>{log}</li>)}
                </ul>
            )
            : (
                <p>Loading ...</p>
            );

    }

}

SupportLogs.defaultProps = {
    logs: null
}

const mapStateToProps = (state) => ({
    logs: state.support.logs
});

const mapDispatchToProps = (dispatch, ownProps) => ({
    fetchBlockLogs: (blockId) => {
        dispatch(ActionTypes.fetchBlockLogs(blockId));
    }
});

export default connect(mapStateToProps, mapDispatchToProps)(SupportLogs);

目前,当我切换一个父<Block/>关闭然后重新打开时,数据会被记住。这是一个很好的功能 - 数据不会经常变化,本地缓存是加速页面的好方法。我的问题是,当我切换第二个<Block/>时,会显示第一个<Logs/>的数据。

我的问题是:如何为<Logs/>的新实例加载新数据?

我是否每次都必须重新加载数据,如果是这样,我是否可以清除logs属性以便重新加载动画?

1 个答案:

答案 0 :(得分:1)

也许可以考虑将商店中的日志更改为加载日志的对象,并按块ID键入:

logs: {
 'someBlockId': [
   'some logline', 
   'some other logline'
 ]
]

让你的reducer通过块id将任何请求的日志添加到这个对象,所以当你请求它们时,它们会被缓存在你的商店中(顺便说一句,我真的很喜欢你的组件调度一个动作来触发其他地方的数据获取作为副作用,而不是在组件内执行获取数据:))。

此reducer假定在动作中调度生成的已获取数据,表示已收到特定块的日志{type: 'UPDATE_LOGS', blockId: 'nic cage', receivedLogsForBlock: ['oscar', 'winning', 'actor']}

logsReducer: (prevState, action) => {
  switch(action.type)
    case 'UPDATE_LOGS':
      return Object.assign({}, prevState, {
        [actions.blockId]: action.receivedLogsForBlock
      })
    default: return prevState
  }
}

在您的组件中,您现在可以通过id查找它们。如果未在logs对象中定义所需的块,那么您知道需要发送加载操作,同时还可以显示加载器

class Logs extends React.Component {

  componentDidMount() {
    const {logs, blockId} = this.props
    if (!logs[blockId]) {
      this.props.fetchBlockLogs(blockId);
    }
  }

  render() {
    const {logs, blockId} = this.props
    return (logs && logs[blockId]) ? (
        <ul>
          {logs[blockId].map((log, i) => <li key={i}>{log}</li>)}
        </ul>
      ) : (
        <p>Loading ...</p>
      )
  }

}

这有logs[blockId] undefined意味着not loaded的额外好处,因此可以区分需要加载的内容和已加载的内容但是有空日志,你的原件会被误认为需要加载