2

假设我有一个名为 Forecast 的最智能组件,它看起来像这样:

function mapStateToProps(state) {
  return {
    dates: state.getIn(['forecast', 'dates']),
    isFetching: state.getIn(['forecast', 'isFetching'])
  };
}

export default connect(mapStateToProps, {
  fetchForecast
})(Forecast));

它包装了一个这样的预测组件:

import { getSummary, getDayForecast } from '../selectors/selectors';
export default class Forecast extends Component {

  render() {
    const { dates, isFetching } = this.props;

    return (
      <div className="row">
        {dates.map(date => (
          <Weather
            key={date}
            date={date}
            getSummary={getSummary}
            getDayForecast={getDayForecast}
          />
       ))}
      </div>
    );
  }
};

在这里,我将 2 个选择器作为道具传递给一个Weather组件。选择器如下所示:

import { createSelector } from 'reselect';
import moment from 'moment';
import { fromJS } from 'immutable';

const getDay = (state, key) => state.getIn(['forecast', 'forecast']).find(x => x.get('id') === key);

export const getSummary = createSelector(
  [getDay],
  (day => {
    const firstPeriod = day.get('periods').first();

    return fromJS({
      date: day.get('date'),
      outlook: firstPeriod.get('outlook'),
      icon: firstPeriod.get('icon')
    });
  })
);

export const getDayForecast = createSelector(
  [getDay],
  (day) => day.get('periods').map(period => fromJS({id: period.get('id') }))
);

我不必将这些选择器作为道具向下传递,我可以轻松地在天气组件中引用它们,但我对如何在天气组件中使用这些选择器感到困惑,因为天气组件也是愚蠢的,不会对国家有任何参考。我只希望顶部有 1 个容器或智能组件,子组件调用或获取传递的道具。

我能看到完成这项工作的唯一方法是拥有一个WeatherContainer看起来像这样的中间组件:

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';

import Weather from '../components/Weather';

import { getSummary, getDayForecast } from '../selectors/selectors';

function mapStateToProps(state, ownProps) {
  return {
    summary: getSummary(state, ownProps.date),
    detail: getDayForecast(state, ownProps.date)
  };
}

export default(connect(mapStateToProps,{}))(Weather);

我会这样称呼:

    {dates.map(date => (
      <WeatherContainer
         key={date}
         date={date}
         getSummary={getSummary}
         getDayForecast={getDayForecast}
         />
    ))}

必须创建这样的容器组件似乎是完全错误的。

我如何在哑组件中使用选择器,或者我如何将它们作为道具传递,同时记住它们也需要引用状态?

4

1 回答 1

5

在你的WeatherContainer mapStateToProps你使用你的选择器,但你仍然将它们作为道具传递下去。这不是必需的。

除此之外,您应该知道创建容器WeatherContainer是做事的正确方式。你永远不应该给组件一个选择器。它们应始终用于mapStateToProps. React-Redux 将在状态更改时重新评估这一点,并在结果不同时告诉 React 更新您的组件。这是非常重要的一点。如果你只是抓取组件内部的状态,无论是否使用选择器,那么 React-Redux都不知道你正在使用这些数据,并且我们无法告诉 React在这些数据发生变化时重新渲染。

现在,很多人都对这个问题感到困惑。有一些愚蠢的组件,它们只是显示东西,还有容器组件,它们一些事情,比如进行 API 调用或实现各种功能。但是当你把一个愚蠢的组件connect带到 Redux 时,这并不能成为一个智能或容器组件。它仍然只显示东西。即使您使用mapDispatchToProps它提供一些事件侦听器,这仍然不能真正使组件变得智能。如果它包含重要的代码mapStateToProps或者mapDispatchToProps我猜它可能会变得聪明。但这就是生活。这些东西之间的界限是模糊的。

Redux Way 是连接所有需要数据的东西。您当然可以将数据传递给子级,就像在普通 React 中一样,但是您可以通过连接组件来创建一个性能更高的应用程序。不过,由您决定。但是仍然很重要的是,无论您从存储中获取数据的任何地方,都应该将其放在一个内部,mapStateToProps以便 React-Redux 可以密切关注数据。只要数据来自 ,您就可以安全地将其从父母传递给孩子mapStateToProps

这意味着将选择器传递给孩子是禁忌。另外,孩子将在哪里获得状态作为参数传递给选择器?它效果不好,所以这不是一个好主意。请注意,无论何时connect创建一个组件,您都不会创建一个全新的组件。只是一个简单的包装器。它应该在很少的几行中包含很少的代码。这不应该让你停下来。去吧。connect那些组件。

我还应该提到,您可以Weather直接在weather.js文件中连接您的组件。除非您打算重用它,否则没有太多需要保留未连接的组件。对于测试,您可以export使用命名导出的未连接组件。如果稍后您决定需要重用该Weather组件,您总是可以轻松地将组件和连接调用分离到单独的文件中。

于 2016-10-04T12:44:55.267 回答