为什么mapStateToProps函数内部的状态总是“未定义”?

时间:2020-06-24 16:12:39

标签: javascript reactjs react-native redux react-redux

我正在使用react native制作一个非常基本的计数器应用,并且我在其中使用redux进行练习,但是遇到了一些问题。

问题

在我的HomeScreen组件的mapStateToProps()函数中,传递的状态参数始终获得 undefined 的值,因此我的UI也未更新。我使用Redux DevTools并监视了状态,并且我知道单击两个按钮后状态会发生变化,但是在mapStateToProps()函数内部,该状态始终为 undefined

请纠正我要去哪里。

这是我的HomeComponent代码

import React, { Component } from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';
import { connect } from 'react-redux';
import * as counterActions from '../redux/actions/counterAction';

class HomeScreen extends Component{

    render(){
        return(
            <View style={styles.homeView}>
                <View>
                <Text style={styles.homeText}>Basic Counter</Text>
                </View>
                <View style={styles.counterStyle}>
                    <View style={{marginRight: 20, width: 50}}>
                    <Button title="-" onPress={() => this.props.decreaseCounter()}></Button>
                    </View>
                    <Text style={{fontSize: 40, color: 'black'}}> {"Value = " + this.props.count} </Text>
                    <View style={{marginLeft: 20, width: 50}}>
                    <Button title="+" onPress={() => this.props.increaseCounter()} ></Button>
                    </View>
                </View>
            </View>
        );
    }
    
}

const styles = StyleSheet.create({
    homeView: {
        flex: 1,
        margin: 24,
        alignItems: 'center',
    },
    homeText: {
        color: 'black',
        fontSize: 24,
    },
    counterStyle: {
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center'
    },
});

function mapStateToProps(state) {
    return {
        count: state.count
    };
}

function mapDispatchToProps(dispatch) {
    return {
        increaseCounter: () => dispatch(counterActions.increaseCounter()),
        decreaseCounter: () => dispatch(counterActions.decreaseCounter())
    };
}

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

这是我的减速器功能

const initialState = {
    count: 0
};

export default function counterReducer(state = initialState, action) {
    switch(action.type){
        case "INCREASE_COUNTER":
            return {
                ...state,
                count: state.count + 1
            };
        case "DECREASE_COUNTER":
            return {
                ...state,
                count: state.count - 1
            };
        default:
            return state;
    }
}

这是我的根目录组件

import React from 'react';
import { Provider } from 'react-redux';
import Main from './components/MainComponent';
import rootReducer from './redux/reducers/index';
import { createStore } from 'redux';

const store  = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

export default function App() {
  return (
    <Provider store={store}>
      <Main />
    </Provider>
  );
}

2 个答案:

答案 0 :(得分:0)

您必须从具有count的特定“减速器”中检索state.counterReducer.count。在这种情况下,您的减速器为counterReducer

Redux始终假定您具有多个reducer,因为每个reducer本身都是一个,并且更改每个reducer不应更新另一个reducer。 Redux使用combineReducers分隔它们。

您可以阅读redux documentation about combining reducers

答案 1 :(得分:0)

要回答这个问题,您还需要显示rootReducercounterActions文件。如果状态无法正确显示在mapStateToProps中,我可能会猜测其中一个文件存在问题。我已经以您的示例为例,并将其移至代码沙箱中,可以准确反映状态和道具。这是我所做的更改。请记住,这是在Web应用程序的上下文中,而不是在本机应用程序的上下文中,但是由于这只是在处理状态,因此无关紧要。

App.js

import React from "react";

import { Provider } from "react-redux";
import { createStore } from "redux";

import Home from "./Home";
import rootReducer from "./reducers";

const store = createStore(rootReducer);

export default function App() {
  return (
    <Provider store={store}>
      <Home />
    </Provider>
  );
}

Home.js

import React, { Component } from "react";
import { connect } from "react-redux";
import counterActions from "./reducers/counter/counterActions";

class HomeScreen extends Component {
  render() {
    return (
      <div>
        <div>
          <p>Basic Counter</p>
        </div>
        <div>
          <div>
            <button onClick={this.props.decreaseCounter}>-</button>
          </div>
          <p style={{ fontSize: 40, color: "black" }}>
            {`value= ${this.props.count}`}
          </p>
          <div style={{ marginLeft: 20, width: 50 }}>
            <button onClick={this.props.increaseCounter}>+</button>
          </div>
        </div>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    count: state.counter.count
  };
}

function mapDispatchToProps(dispatch) {
  return {
    increaseCounter: () => dispatch(counterActions.increaseCounter()),
    decreaseCounter: () => dispatch(counterActions.decreaseCounter())
  };
}

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

reducers / index.js

import { combineReducers } from "redux";

import counterReducer from "./counter/counterReducer";

const rootReducer = combineReducers({
  counter: counterReducer
});

export default rootReducer;

reducers / counter / counterReducer.js

import { actionConstants } from "./counterActions";

const initialState = {
  count: 0
};

export default function counterReducer(state = initialState, action) {
  switch (action.type) {
    case actionConstants.INCREASE_COUNTER:
      return {
        ...state,
        count: state.count + 1
      };
    case actionConstants.DECREASE_COUNTER:
      return {
        ...state,
        count: state.count - 1
      };
    default:
      return state;
  }
}

reducers / counter / counterActions.js

const actionConstants = {
  INCREASE_COUNTER: "INCREASE_COUNTER",
  DECREASE_COUNTER: "DECREASE_COUNTER"
};

const counterActions = {
  increaseCounter() {
    return {
      type: actionConstants.INCREASE_COUNTER
    };
  },

  decreaseCounter() {
    return {
      type: actionConstants.DECREASE_COUNTER
    };
  }
};

export { counterActions as default, actionConstants };

Heres's a link to the working sandbox