使用mapStateToProps基于动态路径参数渲染组件并重新选择

时间:2017-01-10 15:41:13

标签: javascript reactjs redux react-redux reselect

我将各种rooms的数据存储在全局应用容器中。我有一个名为roomDetails的子容器,它使用重选选择器使用ownProps.params.slug从全局状态中选择一个房间。这是使用mapStateToProps完成的。

我的问题是当我从:

更改路线参数(rooms/:roomId)时

rooms/roomid1

rooms/roomid2

组件室道具没有更新。

我正在使用Link更改路线:

<Link to={"/room/roomid1"} key={"room-roomid1"}>room 1</Link>

当路线参数更改时,如何让组件的room道具从全球房间状态重新选择房间?

注意,房间道具会在第一页加载时加载,或者如果我去了一条在动态路线之外的路线,然后返回。在相同的动态路由之间切换时,它们只是无法正确加载,其中只有组件属性(路径参数)正在发生变化。

RoomDetails / index.js

const mapStateToProps = (state, ownProps) => {
  return createStructuredSelector({
    room: selectRoom(ownProps.params.roomId),
  });
}

...

  render() {
    let roomContent = null;
    if (this.props.room) {
      roomContent = (
        <div>
          {this.props.room.get('name')}
        </div>
      );
    }
    return (
      <div>
        {roomContent}
      </div>
    );
  }

selectors.js

import { createSelector } from 'reselect';

const selectGlobal = () => (state) => state.get('global');

const selectRooms = () => createSelector(
  selectGlobal(),
  (globalState) => globalState.get('rooms')
);

const selectRoom = (roomId) => createSelector(
  selectRooms(),
  (roomsState) => roomsState && roomsState.get(roomId)
);

2 个答案:

答案 0 :(得分:0)

重新选择只会响应传递给第一个参数的任何变量。因此,每当路由更改时,您必须更新某个变量。有两种选择可以想到:

  • 实施react-router-redux,然后在您的选择器

  • 中回复它
  • 发送一个事件,用于更新商店中安装在该路径上的组件中的roomId

对于第二个选项,你会做这样的事情。假设此组件已安装在路径/rooms/:roomId

class Rooms extends Component {
  changeRoom = (roomId = this.props.roomId) => this.props.setRoom(roomId);

  componentDidMount() {
    this.changeRoom();
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.roomId !== nextProps.roomId) {
      this.changeRoom(nextProps.roomId);
    }
  }
}

说这会更新state.room.selected。您可以在选择器中指定。

import { createSelector } from 'reselect';

const getRooms = state => state.rooms.data;
const getSelected = state => state.rooms.selected;

export const getCurrentRoom = createSelector(
  [ getRooms, getSelected ],
  (rooms, selected) => rooms.find(room.id === selected)
)

答案 1 :(得分:0)

我从selectRoom删除了参数并将mapStateToProps更改为:

const mapStateToProps = createStructuredSelector({
  room: selectRoom(),
});

然后我更新了这样的选择器,它正在工作......

const selectGlobal = () => (state) => state.get('global');

const selectedRoom = () => (state, props) => props && props.params.roomId;

const selectRooms = () => createSelector(
  selectGlobal(),
  (globalState) => globalState.get('rooms')
);

const selectRoom = () => createSelector(
  selectRooms(),
  selectedRoom(),
  (roomsState, roomId) => roomsState.get(roomId)
);

我还是不明白为什么当我将props.params.roomId传递给它时,选择器没有被调用...

也许因为selectRooms()没有参数,它总是被调用?

相关问题