简体   繁体   中英

React Redux Life Cycle Confussion

I have been reading several documents and watching videos regarding React Redux, but since all of them are different I wasn't able to apply that knowledge to some real project.

I will try to enumarate the process in order to use React Redux together.

Directory Structuring

  • project
    • src
      • components
        • User
          • index.js (Container component)
          • page.js (Presentational component)
      • actions
        • users.js
        • index.js (exports actionCreators combination)
      • reducers
      • constants
        • actionTypes.js
      • services
        • users.js
      • index.js
      • store.js
      • public
      • index.html

Redux Setup

  1. We create constants in project/src/constants/actionTypes.js :
     export const CREATE_USER = 'CREATE_USER'; export const DELETE_USER = 'DELETE_USER'; export const UPDATE_USER = 'UPDATE_USER'; 
  2. We create actionCreators en project/src/actions/users.js y luego se combinan en project/src/actions/index.js :

    • users.js

     import { CREATE_USER } from '../constants/actionTypes'; export default function createUser(user) { type: CREATE_USER, user } 
    • index.js

     import { createUser } from './users'; export default { createUser } 
  3. We create reducers in project/src/reducers/users.js and they are combined in project/src/reducers/index.js using combineReducers() :

    • users.js

     import { CREATE_USER, UPDATE_USER, DELETE_USER } from '../constants/actionTypes'; import { createUser } from '../services/users'; const initialState = { name: '', password: '', email: '' } export default function users(state = initialState, action) { switch (action.type) { case CREATE_USER: state = createUser(action.user); return state; } } 
    • index.js

     import users from './users'; export default combineReducers({ users }) 
  4. We create store in project/src/store.js :

     import { createStore } from 'redux'; import reducers from './reducers'; export const store = createStore(reducers); 

    React Redux Setup

  5. We wrap component application <Provider> in project/src/index.js :

     import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { store } from './store'; const Root = () => ( ` <Provider store={store}> <App /> </Provider> ` ) ReactDOM.render(Root, document.getElementById('root'); 
  6. We transform component state to properties with mapStateToProps in project/src/components/User/index.js :

     import React, { Component } from 'react'; import { createUser } from '../../actions/users'; import Page from './page'; class User extends Component { render() { return <Page users={this.props.users} /> } } const mapStateToProps = state => ({ users: this.props.users // what is mapped here? }); const mapDispatchToProops = dispatch => ({ // what about here? }); export default connect(mapStateToProps, mapDispatchToProps)(User); 

So, the question would be, is this React-Redux cycle well formed? What is missing or wrong?

Yes, the folder structure works well. As for the "fetch" or "service" functionality you're talking about, I'll give you an example of what actions and reducers both should, in a basic example, do.

So if you're working with a backend which you're "fetching" anything from, I'd recommend adding that functionality in the action, not the reducer:

import { USERS_FETCHED } from '../constants/actionTypes';
import { baseUrl } from "../constants/baseUrl";

const usersFetched = users => ( { // action to dispatch
  type: USERS_FETCHED,
  users,
} );

export const fetchUsers = () => ( dispatch ) => { // export for mapDispatchToProps
  request( `${ baseUrl }/users` )
    .then( response => {
      dispatch( usersFetched( response.body ) ); // dispatch the action to reducer
    } )
    .catch( console.error );
}; // in your case you import createUser(), but it works either way

Now the action is concerned with functionality, in contrast the reducer is only concerned with managing the Redux state:

import { USERS_FETCHED } from "../constants/actionTypes";

export default ( state = null, action = {} ) => {
  switch ( action.type ) {
    case USERS_FETCHED:
      return action.users;

    default:
      return state;
  }
};

Functionality in the reducer is fine, but it should only be concerned with managing state. You can imagine how cluttered the code could get if you start fetching any data here, not to mention problems with asynchronicity. Of course, this is just one way to do it, but it works solidly. Hope this helps you in some way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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