简体   繁体   English

如何使用react和redux在表中提供动态计算的数据

[英]How to provide dynamically calculated data in table using react and redux

How to use redux and react to render dynamically calculated data using function from refux?如何使用 redux 和 react 使用 refux 中的函数来呈现动态计算的数据? In more details: I am trying to render table with two columns (name, share).更多详细信息:我正在尝试使用两列(名称、共享)呈现表。 Name comes from entity.name and share is calculated data using entity.id and remote service. Name 来自 entity.name 和 share 是使用 entity.id 和远程服务计算的数据。 Currently I have dynamically rendered table with rows per entity with it's name, but I am unable to pass calculated data by entity.id.目前,我已经动态呈现了每个实体的行及其名称,但我无法通过 entity.id 传递计算数据。

I've tried use redux action to do that, but now I understand that redux actions does not return any value, but modifies states in it's store.我已经尝试使用 redux action 来做到这一点,但现在我明白 redux actions 不返回任何值,而是修改其存储中的状态。 The code I provided below using {calculateShare(entity.id)} gives me error that it returns array {type, payload}.我在下面使用 {calculateShare(entity.id)} 提供的代码给出了它返回数组 {type, payload} 的错误。 Another option might be to build key/value array in redux store and use it in the react table by getting array value using entity.id as a key, but I'm not sure how to do that properly in a reducer and react code.另一种选择可能是在 redux 存储中构建键/值数组,并通过使用 entity.id 作为键获取数组值在反应表中使用它,但我不确定如何在减速器和反应代码中正确执行此操作。

Reducer looks like this:减速器看起来像这样:

export const getCalculatedShareById: IPayloadResult<String> = id => {
  const requestUrl = `${apiUrl}/${id}/calculated-share`;
  return {
    type: ACTION_TYPES.FETCH_ENTITY_CALCULATED_SHARE,
    payload: axios.get<String>(requestUrl)
  };
};

My react example for Home page using reducer:我使用减速器的主页反应示例:

export class Home extends React.Component {
  componentDidMount() {
    this.props.getEntities();
  }

  render() {
    const { entitiesList, getCalculatedShareById } = this.props;
    return (
      <Row>
        <Col>
          <Table>
            <thead>
              <tr>
                <th>Name</th>
                <th>Share</th>
              </tr>
            </thead>
            <tbody>
              {entitiesList.map((entity, i) => (
                <tr key={`entity-${i}`}>
                  <td>{entity.name}</td>
                  <td>{getCalculatedShareById(entity.id)}</td>
                </tr>
              ))}
            </tbody>
          </Table>
        </Col>
      </Row>
    );
  }
}

const mapStateToProps = storeState => ({
  entitiesList: storeState.myReducer.entities
});

const mapDispatchToProps = { getEntities, getCalculatedShareById};

type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = typeof mapDispatchToProps;

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

Please help me understand what is the best way to resolve such problem and provide some examples if possible.请帮助我了解解决此类问题的最佳方法是什么,并在可能的情况下提供一些示例。

The flow should be like this 流程应该是这样的

  1. Fire a dispatch. 发射一次调度。
  2. Update entity in state through dispatch in reducer. 通过reducer中的dispatch更新状态中的entity
  3. In mapStateToProps entity from state is already imported to component, this variable gets updated after we fire our action (precisely in reducer). mapStateToProps来自state的entity已经导入到组件中,此变量在我们触发操作后更新(正好在reducer中)。
  4. After we fire the dispatch we have access to modified variable through this.props.entityList . 在我们发出调度之后,我们可以通过this.props.entityList访问修改后的变量。

The missing in the above execution is the reducer, So we need to implement a reducer that takes state and action --> {type: x, payload: y} as parameter and modifies the entity property of state and returns modified state 上面执行中缺少的是reducer,所以我们需要实现一个reducer,它接受state和action - > {type: x, payload: y}作为参数并修改state的entity属性并返回修改后的state

I ended up with creating web service method which calculates share amount per entity, puts this data to map and returns to react using axios and redux. 我最终创建了Web服务方法,该方法计算每个实体的份额,将此数据放入映射并返回使用axios和redux进行反应。 Not sure if this is the best solution to my problem, but it works. 不确定这是否是我问题的最佳解决方案,但它确实有效。

Example of my working code => reducer: 我的工作代码示例=> reducer:

export const ACTION_TYPES = {
  FETCH_ENTITY_SHARE_AMOUNT: 'entity/FETCH_ENTITY_SHARE_AMOUNT'
};

const initialState = {
  loading: false,
  errorMessage: null,
  entitiesShareAmountMap: Map,
  updating: false,
  updateSuccess: false
};

export type EntityState = Readonly<typeof initialState>;

// Reducer

export default (state: EntityState = initialState, action): EntityState => {
  switch (action.type) {
    case REQUEST(ACTION_TYPES.FETCH_ENTITY_SHARE_AMOUNT):
      return {
        ...state,
        errorMessage: null,
        updateSuccess: false,
        loading: true
      };
    case FAILURE(ACTION_TYPES.FETCH_ENTITY_SHARE_AMOUNT):
      return {
        ...state,
        loading: false,
        updating: false,
        updateSuccess: false,
        errorMessage: action.payload
      };
    case SUCCESS(ACTION_TYPES.FETCH_ENTITY_SHARE_AMOUNT):
      return {
        ...state,
        loading: false,
        entitiesShareAmountMap: action.payload.data
      };
    default:
      return state;
  }
};

const apiUrl = 'api/entities';

// Actions

export const getEntitiesShareAmountMap: IPayloadResult<any> = () => {
  const requestUrl = `${apiUrl}/entities-share-amount`;
  return {
    type: ACTION_TYPES.FETCH_ENTITY_SHARE_AMOUNT,
    payload: axios.get<Map<String, String>>(requestUrl)
  };
};

react component: 反应成分:

export class Home extends React.Component {
  componentDidMount() {
    this.props.getEntities();
    this.props.getEntitiesShareAmountMap();
  }

  render() {
    const { entitiesList, entitiesShareAmountMap } = this.props;
    return (
      <Row>
        <Col>
          <Table>
            <thead>
              <tr>
                <th>Name</th>
                <th>Share</th>
              </tr>
            </thead>
            <tbody>
              {entitiesList.map((entity, i) => (
                <tr key={`entity-${i}`}>
                  <td>{entity.name}</td>
                  <td>{entitiesShareAmountMap[lottery.id]}</td>
                </tr>
              ))}
            </tbody>
          </Table>
        </Col>
      </Row>
    );
  }
}

const mapStateToProps = storeState => ({
  entitiesList: storeState.myReducer.entities,
  entitiesShareAmountMap: storeState.myReducer.entitiesShareAmountMap
});

const mapDispatchToProps = { getEntities, getEntitiesShareAmountMap };

type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = typeof mapDispatchToProps;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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