为什么 react-redux 会创建多个状态?

Why is react-redux creating multiple states?

本身不是问题,只是一个问题。

我正在使用 React-Redux 来处理我的应用程序状态。我已将名为 Academy 的最高级别组件与 mapStateToPropsmapDispatchToProps

连接起来

然后我有一个子组件,SlideOverBar,它只为使用以下代码行的调度连接:

export default connect(null, mapDispatchToProps)(SlideOverBar);

现在,一切都按预期工作,但出于某种原因,在我的 React 开发人员工具中,SlideOverBar 组件具有状态的完整副本。此状态永远不会更新,但我担心它可能会导致任何问题。谁能告诉我 - 这正常吗?如果不正常,我该怎么办。

为了澄清,这里有一些开发者工具的屏幕截图:

Academy 组件,在需要时更新状态。可以看到workshopSelection.selectedLevel条状态已经从null更新为4,应该是:

SlideOverBar 组件。这里的状态是Academy中状态的副本。它从不更新(这很好 - Academy 状态应该控制应用程序)但我不明白为什么它首先存在。此组件上的 mapStateToProps 值设置为 null

更新

这是每个组件的完整代码。

学院:

import React, {Component, PropTypes} from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {showSlideOver, hideSlideOver} from '../../data/actions/actions';
import styles from '../../cssPartials/Academy.css';
import TopBar from './../TopBar';
import SideMenu from './../SideMenu';
import ViewPort from './../ViewPort';
import SlideOverBar from '../slideOver/SlideOverBar';

class Academy extends Component {

    render(){

        return (
            <div className={styles.academy}>
                <div className={styles.spacer} />
                <TopBar />
                <div className={styles.container}>
                    <SideMenu />
                    <ViewPort>
                        {this.props.children}
                    </ViewPort>
                </div>
                <SlideOverBar slideOver={this.props.slideOver}
                              workshopSelection={this.props.workshopSelection}
                              slideOverAction={this.props.hideSlideOver}
                />
            </div>
        )   
    }

}

function mapStateToProps(state){
    return {
        slideOver: state.slideOver,
        workshopSelection: state.workshopSelection
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({ showSlideOver: showSlideOver, hideSlideOver: hideSlideOver }, dispatch);
}

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

SlideOverBar:

import React, {Component} from "react";
import styles from '../../cssPartials/slideOverBar.css';
import SlideOverBarTop from './SlideOverBarTop';
import NewWorkshop from './NewWorkshop';
import EditWorkshop from './EditWorkshop';
import UploadSlides from './UploadSlides';
import UploadWorkbook from './UploadWorkbook';
import ViewWorkbook from './ViewWorkbook';
import UploadResources from './UploadResources';
import ViewResources from './ViewResources';
import constants from '../../data/constants.js';
import {chooseLevel, chooseVenue, chooseUnit, showCourses, dayCounter, chooseTutor, resetWorkshops } from '../../data/actions/actions';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

class SlideOverBar extends Component {

    loadContent(testCase){
        switch (testCase){
            case constants.ADD_WORKSHOP:
                return <NewWorkshop properties = {this.props} />
            case constants.EDIT_WORKSHOP:
                return <EditWorkshop properties = {this.props} />
            case constants.UPLOAD_SLIDES:
                return <UploadSlides properties = {this.props} />
            case constants.UPLOAD_WORKBOOK:
                return <UploadWorkbook properties = {this.props} />
            case constants.VIEW_WORKBOOK:
                return <ViewWorkbook properties = {this.props} />
            case constants.UPLOAD_RESOURCES:
                return <UploadResources properties = {this.props} />
            case constants.VIEW_RESOURCES:
                return <ViewResources properties = {this.props} />
            default:
                return <div>Uh oh, something went wrong!</div>
        }

    }

    render(){       
        return (
            <div className={this.props.slideOver.visible ? `${styles.slideOverBar} ${styles.visible}`
                                    : styles.slideOverBar }>
                <SlideOverBarTop slideOverAction = {this.props.slideOverAction}
                                 reset = {this.props.resetWorkshops}
                                 title = {this.props.slideOver.content} />
                {this.loadContent(this.props.slideOver.content)}
            </div>
        )
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({ chooseLevel, chooseVenue, chooseUnit, showCourses, chooseTutor, resetWorkshops }, dispatch);
}


export default connect(null, mapDispatchToProps)(SlideOverBar);

有什么想法吗?

这没什么好担心的。您只是看到 connect 函数使用的 HOC Connect。该组件使用下面的整个商店 context。这只是对商店的引用,并非复制。

如果您签出 this line of code from connect,您可以看到 Connect 组件正在拉取整个存储并将其设置为其 state

const storeState = this.store.getState()
this.state = { storeState }

这允许 Connect 组件然后将特定的 store 值与 mapStateToProps 绑定。但是由于您传递的是 null 它将默认为:

const defaultMapStateToProps = state => ({})