React 子组件在第一次加载时不接收道具

React child component does not receive props on first load

我正在父 'wrapper' 组件中获取数据并将其传递给两个子组件。一个子组件接受得很好,另一个没有。

在容器中:

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

在包装器组件中,我渲染了两个组件,触发数据获取并将道具向下传递给子组件(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>
    );
  }
}

更新: 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)

为什么不一样,请问如何解决?

谢谢, 罗马

我认为问题可能出在您的 select 上,尤其是这一个,其组成部分被立即执行(没有获取数据值),因此值不会随着记忆而改变。这意味着如果基础数据从获取的数据发生变化,它不会导致组件更新

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

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

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

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