mapStateToProps和mapDispatchToProps:将IDE转换为"请参阅"道具

时间:2016-08-09 07:38:51

标签: redux

问题:IDE无法通过connect()

解析传递给组件的道具

注意:这不是错误,但对编码人员造成不便

假设我已通过connect()将此React组件连接到Redux:

class SomeComponent extends Component {
    render() {
        return (
            {this.props.someObject ? this.props.someObject : ''}
        );
    }
}

function mapStateToProps(state) {
    return {
        someObject: new SomeObject(state.someReducer.someObjectInfo),
    };
}

function mapDispatchToProps(dispatch) {
    return {
        // ...
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(ChatsList);

我正在使用IntelliJ IDE,并且以上述方式连接到组件的任何道具(例如someObject)都会收到未解决的变量警告。如果someObject有一些属性/方法,它们既不会被解析也不会显示在代码建议中(这些都非常有用)。

解决方法

  1. statedispatch自己作为道具传递:

    function mapStateToProps(state) {return {state};}
    function mapDispatchToProps(dispatch) {return {dispatch};}
    
  2. 在构造函数中定义我的变量(而不是通过道具):

    constructor(props) {
        this.someVar = props.state.someReducer.someVar;
        this.someObj = new SomeObject(props.state.someReducer.someObjectInfo;
    }
    
  3. 每当道具改变时手动更新变量:

    componentWillReceiveProps(nextProps) {
        someObject.update(nextProps.state.someReducer.someObjectInfo);
    }
    
  4. 缺点是在componentWillReceiveProps中有额外的样板逻辑,但现在IDE很乐意解析变量并且代码建议有效。

    问题

    解决方法更好吗?到目前为止,我一直在使用它,到目前为止还没有发现任何其他缺点。有没有更好的方法让IDE了解代码?

    动机(详细;仅对那些对我为什么要完成上述工作感兴趣的人)

    Redux教程展示了一种将状态/调度连接到道具的简单方法,例如:

    function mapStateToProps(state) {
        users: state.usersReducer.users
        chats: state.chatsReducer.chats        
    }
    
    function mapDispatchToProps(dispatch) {
        addUser: (id) => dispatch(usersActions.addUser(id))
        addChatMsg: (id, msg) => dispatch(chatsActions.addChatMsg(id, msg)
    }
    

    在上面的例子中,组件的编码器需要知道每个相关的减速器。名称及其状态变量。这对于编码人员来说可能会变得混乱。相反,我想从组件中抽象出这些细节。一种方法是使用"模块"接受statedispatch的类,并提供所有get / set方法:

    class Chats {
        // Actions
        static ADD_MESSAGE = "CHATS/ADD_MESSAGE";
    
        constructor(globalState, dispatch) {
            this.chatsState = globalState.chats;
            this.dispatch = dispatch;
        }
    
        // Get method
        getChats() {
            return this.chatsState.chats;
        }
    
        // Set method
        addChatMessage(id, msg) {
            return this.dispatch({
                type: Chats.ADD_MESSAGE,
                id,
                msg
            };
        }
    
        // Called by componentWillReceiveProps to update this object
        updateChats(nextGlobalState) {
            this.chatsState = nextGlobalState.chats;
        }
    }
    

    现在,如果一个组件需要Chats模块,编码器就会这样做:

    class SomeComponent extends Component {
        constructor(props) {
            this.chats = new Chats(props.state, props.dispatch);
        }
    
        componentWillReceiveProps(nextProps) {
            this.chats.updateChats(nextProps);
        }
    
        // ...
    }
    

    现在,所有Chats get / set方法和属性都可用,并且将被IDE选中。

1 个答案:

答案 0 :(得分:0)

我认为最新的Idea现在可以理解通过propTypes定义的组件属性,并为它们提供代码完成。所以你只需声明propTypes。它甚至不是一种解决方法,在我看来这是一个很好的做法。

class ChatsList extends Component {
    static propTypes = {
      someObject: PropTypes.shape({
        color: PropTypes.string,
        someFunc: PropTypes.func
      }),
      someDispatcher: PropTypes.func
    };

    render() {
        return (
            {this.props.someObject ? this.props.someObject : ''}
        );
    }
}

function mapStateToProps(state) {
    return {
        someObject: new SomeObject(state.someReducer.someObjectInfo),
    };
}

function mapDispatchToProps(dispatch) {
    return {
        someDispatcher: Actions.someDispatcher
        // ...
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(ChatsList);

此外,传递整个状态是一个坏主意,因为如果整个状态发生任何变化,组件将接收道具并获得重新渲染(除非您提供shouldComponentUpdate