0

I am storing data for various rooms in a global app container. I have a sub-container called roomDetails that uses a reselect selector to select a room from the global state using ownProps.params.slug. This is done using mapStateToProps.

My problem is that when I change route params (rooms/:roomId) from:

rooms/roomid1

to

rooms/roomid2

the component room props are not updating.

I'm changing the route using Link:

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

How can I get the component's room props to reselect a room from the global rooms state when the route params change?

Note, the room props load as they should on first page load, or if i go to a route that's outside of the dynamic route, and then return. They just don't load correctly when switching between the same dynamic route, where only component properties (route params) are changing.

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)
);
4

2 回答 2

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()没有参数它总是被调用?

于 2017-01-10T18:41:53.900 回答
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)
)
于 2017-01-10T16:12:07.973 回答