【问题标题】:Rendering a component based on dynamic route params with mapStateToProps and reselect使用 mapStateToProps 渲染基于动态路由参数的组件并重新选择
【发布时间】:2017-01-10 15:41:13
【问题描述】:

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

我的问题是,当我从以下位置更改路由参数 (rooms/:roomId) 时:

rooms/roomid1

到

rooms/roomid2

组件房间道具没有更新。

我正在使用链接更改路线:

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

【问题讨论】:

    标签: javascript reactjs redux react-redux reselect


    【解决方案1】:

    重新选择只会响应传递给第一个参数的任何变量。因此,每当该路由发生变化时,您都必须更新一些变量。有两种选择:

    • 实现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)
    )
    

    【讨论】:

    • 不应该选择器“selectRoom”响应,因为我传递给它(ownProps.params.roomId)IS改变?
    • 你能控制台记录它以确认它正在改变吗?
    • 当我执行“componentWillReceiveProps(nextProps) { console.log('Next room:', nextProps.params.roomId); }”时,每次我单击指向的链接时,它都会打印正确的房间 ID更衣室
    • 所以 props.params.roomId(路由参数)正在更新,但 props.params.room 没有。
    • 我的意思是,将它记录在选择器中。例如:(rooms, selected) =&gt; { console.log(rooms, selected); return rooms.get(selected) }
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2019-11-26
      • 1970-01-01
      • 2020-08-16
      • 2020-09-13
      • 2020-07-24
      • 2018-11-02
      • 2021-09-30
      • 1970-01-01
      • 2020-08-15
      相关资源
      最近更新 更多