React子组件在首次加载时不会收到道具

时间:2017-11-24 10:03:29

标签: reactjs redux redux-saga reselect

我在父“包装器”组件中获取数据并将其传递给两个子组件。一个子组件很好地接收它,另一个子组件没有。

在容器中:

const mapStateToProps = createStructuredSelector({
  visitedCountriesList: getVisitedCountriesList(),
  visitedCountriesPolygons: getVisitedCountriesPolygons()
});

export function mapDispatchToProps(dispatch) {
  return {
    loadVisitedCountries: () => {
      dispatch(loadVisitedCountriesRequest())
    },
  };
}
在redux-saga中的

我从API获取数据并存储它们:

function mapPageReducer(state = initialState, action) {
   switch (action.type) {
     case FETCH_VISITED_COUNTRIES_SUCCESS:
       return state
         .setIn(['visitedCountriesPolygons', 'features'], action.polygons)
 }

选择器:

const getVisitedCountriesList = () => createSelector(
  getMapPage,
  (mapState) => {
    let countriesList = mapState.getIn(['visitedCountriesPolygons', 'features']).map(c => {
      return {
        alpha3: c.id,
        name: c.properties.name
      }
    });
    return countriesList;
  }
)

const getVisitedCountriesPolygons = () => createSelector(
  getMapPage,
  (mapState) => mapState.get('visitedCountriesPolygons')
)

在包装器组件中,我呈现两个组件,触发数据获取并将props传递给子组件(visitedCountriesPolygons和visitedCountriesList):

class MapView extends React.Component {
  constructor(props) {
    super(props)
    this.props.loadVisitedCountries();
  }

  render() {
    return (
      <div>
        <Map visitedCountriesPolygons={this.props.visitedCountriesPolygons} />
        <MapActionsTab visitedCountriesList={this.props.visitedCountriesList} />
      </div>
    );
  }
}

然后,在第一个子组件Map中,我很好地接收了道具并且可以构建地图:

componentDidMount() {
    this.map.on('load', () => {
      this.drawVisitedPolygons(this.props.visitedCountriesPolygons);
    });
};

但是在第二个组件中,MapActionsTab道具不是在初始渲染时收到的,而是仅在任何更新之后:

class MapActionsTab extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    let countriesList = this.props.visitedCountriesList.map(country => {
      return <li key={country.alpha3}>{country.name}</li>;
    }) || '';

    return (
      <Wrapper>
          <div>{countriesList}</div>
      </Wrapper>
    );
  }
}

UPD: Saga从API获取数据:

export function* fetchVisitedCountries() {
  const countries = yield request
    .get('http://...')
    .query()
    .then((res, err) => {
      return res.body;
  });
  let polygons = [];
  yield countries.map(c => {
    request
      .get(`https://.../${c.toUpperCase()}.geo.json`)
      .then((res, err) => {
        polygons.push(res.body.features[0]);
      })
  });
  yield put(fetchVisitedCountriesSuccess(polygons));
}

和一个简单的reducer来存储数据:

case FETCH_VISITED_COUNTRIES_SUCCESS:
       return state
         .setIn(['visitedCountriesPolygons', 'features'], action.polygons)

为什么它与众不同以及如何解决呢?

感谢, 罗马

2 个答案:

答案 0 :(得分:1)

显然,这是正确的,这只是另一个地方的一个小问题(这里没有粘贴,也没有报告错误)。 彻底清理和重构后,它按预期工作。

结论:始终保持代码清洁,使用linter并遵循最佳实践:)

答案 1 :(得分:0)

我认为问题可能在你的选择器中,特别是这个问题,它的组成部分是立即执行的(没有提取的数据值),因此值不会随着它的记忆而改变。这意味着如果基础数据从获取的数据发生更改,它将不会导致组件更新

const mapStateToProps = createStructuredSelector({
  visitedCountriesList: getVisitedCountriesList, // should not execute ()
  visitedCountriesPolygons: getVisitedCountriesPolygons // should not execute ()
});

通过不立即执行组合选择器,mapStateToProps将在每次状态更改时调用它们,并且它们应该选择新值并导致反应组件的自动更新