简体   繁体   English

React Redux将状态作为道具传递给组件

[英]React Redux pass state as props to component

In my React Redux application, when the main page loads, I want to fetch the data from an API and display it for the user to see. 在我的React Redux应用程序中,当主页面加载时,我想从API获取数据并显示它供用户查看。 The data is being fetched from the action and the state is being updated. 正在从操作中获取数据,并且正在更新状态。 However, I am not seeing the state as a prop of the component. 但是,我没有将该州视为该组成部分的支柱。 Not sure what's not hooked up correctly. 不确定什么没有正确连接。

Home component : 家庭组件:

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actions from '../actions/actions';
import '../styles/homeStyles.css';

class Home extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    this.props.actions.fetchMovies();
  }

  render() {
    const { movies, isFetching, errorMessage } = this.props;

    if (isFetching && !movies.length) {
      return <p>Loading...</p>;
    }

    //will display movies when I have access to state
    return (
      <div>
        <h1>React Starter App</h1>
        <h2>This is the home page</h2>
      </div> 
    );
  }
}

Home.proptypes = {
  actions: PropTypes.object.isRequired,
  dispatch: PropTypes.func.isRequired,
  movies: PropTypes.array.isRequired,
  isFetching: PropTypes.bool.isRequired,
  errorMessage: PropTypes.string
};

function mapStateToProps(state) {
  return {
    movies: state.movies,
    isFetching: state.isFetching,
    errorMessage: state.errorMessage
  };
}

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

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

store : 商店:

import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import createLogger from 'redux-logger';
import { syncHistoryWithStore } from 'react-router-redux';
import { browserHistory } from 'react-router';

import rootReducer from '../reducers/index';

const initialState = {
  movies :{
    movies: [],
    isFetching: false,
    errorMessage: null,
    firstName: null,
    lastName: null,
    email: null
  }
};

const store = createStore(rootReducer, initialState, applyMiddleware(thunkMiddleware, createLogger()));

export const history = syncHistoryWithStore(browserHistory, store);

if (module.hot) {
  module.hot.accept('../reducers/', () => {
    const nextRootReducer = require('../reducers/index').default;
    store.replaceReducer(nextRootReducer);
  });
}

export default store;

App : 应用:

import React, { Component } from 'react';
import Navbar from './Navbar';

class App extends Component {
  render() {
    return (
      <div>
        <Navbar />
        <div className="container">
          {this.props.children}
        </div>
      </div>
    );
  }
}

export default App;

Index : 指数:

import React from 'react';
import {render} from 'react-dom';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute } from 'react-router';
import store, { history } from './store/store';
require('./favicon.ico');
import App from './components/App';
import Home from './components/Home';
import Contact from './components/Contact';
import NotFoundPage from './components/NotFoundPage';

const router = (
  <Provider store={store}>
    <Router history={history} >
      <Route path="/" component={App}>
        <IndexRoute component={Home} />
        <Route path="/contact" component={Contact} />
        <Route path="*" component={NotFoundPage} />
      </Route>
    </Router>
  </Provider>
);

render(router, document.getElementById('app'));

Reducer : 减速机:

import * as constants from '../constants/constants';

const initialState = {
  movies: [],
  isFetching: false,
  errorMessage: null
};

const moviesReducer = (state = initialState, action) => {
  switch (action.type) {
    case constants.FETCH_MOVIES : 
      return {
        ...state,
        isFetching: true
      };
    case constants.FETCH_MOVIES_SUCCESS :
      return {
        ...state,
        movies: [action.data],
        isFetching: false
      };
    case constants.FETCH_MOVIES_ERROR :
      return {
        ...state,
        isFetching: false,
        errorMessage: action.message
      };
    default :
      return state;
  }
};

export default moviesReducer;

I was accessing state incorrectly in my mapStateToProps function. 我在mapStateToProps函数中错误地访问了状态。 When I placed a debugger inside the function I was able to see the structure of state and it did not match what I was trying to access there. 当我在函数中放置一个调试器时,我能够看到状态结构,它与我试图访问的那个不匹配。

Since my store state looked like this : 由于我的商店状态如下所示:

const initialState = {
  movies :{
    movies: [],
    isFetching: false,
    errorMessage: null,
    firstName: null,
    lastName: null,
    email: null
  }
};

I needed to change my mapStateToProps function in my component to look like this : 我需要在我的组件中更改我的mapStateToProps函数,如下所示:

function mapStateToProps(state) {
  return {
    movies: state.movies.movies,
    isFetching: state.movies.isFetching,
    errorMessage: state.movies.errorMessage
  };
}

This allowed everything to be mapped correctly and to have access to the state inside the component. 这允许正确映射所有内容并访问组件内的状态。

Since then I refactored my state in the store to look like this : 从那时起,我在商店中重构我的状态看起来像这样:

const initialState = {
  movies: {
    movies: [],
    isFetching: false,
    errorMessage: null
  },
  form: {
    firstName: null,
    lastName: null,
    email: null
  }
};

and my mapStateToProps function to look like : 和我的mapStateToProps函数看起来像:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM