DEV Community

Yogesh Datir
Yogesh Datir

Posted on • Edited on

5 4

React-Redux boiler-plate

Steps to use redux state management:

  1. store.js
  2. reducers (rootReducer and others)
  3. wrap App.js with Provider
  4. add actions and types
  5. use redux in components with connect() method.

Detail Guide to create a React-Redux boiler-plate (with Redux-thunk as a middleware):

1. Install redux and necessary libraries.

npm i redux react-redux redux-thunk redux-devtools-extension

  • React Redux is the official React binding for Redux. It lets your React components read data from a Redux store, and dispatch actions to the store to update data.
  • Redux Thunk: With a plain basic Redux store, you can only do simple synchronous updates by dispatching an action. Middleware extends the store's abilities, and let you write async logic that interacts with the store.
  • Redux Devtools Extension: to enable easy debugging and time travel.

2. Create src/store.js.

   import { createStore, applyMiddleware } from 'redux';
   import { composeWithDevTools } from 'redux-devtools-extension';
   import thunk from 'redux-thunk';
   import rootReducer from './reducers';

   const initialState = {};

   const middleware = [thunk];

   const store = createStore(
    rootReducer,
    initialState,
    composeWithDevTools(applyMiddleware(...middleware)),
   );

   export default store;
Enter fullscreen mode Exit fullscreen mode

3. Create reducers/index.js.

   import { combineReducers } from 'redux';

   export default combineReducers({});
Enter fullscreen mode Exit fullscreen mode

4. Wrap all root component - App with Provider.

   import React from 'react';

   import { Provider } from 'react-redux';
   import store from '../store';

   function App() {
     return (
       <Provider store={store}>
         <>This is App Component</>
       </Provider>
     );
   }

   export default App;
Enter fullscreen mode Exit fullscreen mode

5. Create actions/types.js.

   export const FETCH_POSTS = 'FETCH_POSTS';
   export const NEW_POST = 'NEW_POST';
Enter fullscreen mode Exit fullscreen mode

6. Create actions/clientActions.js.

   import { FETCH_POSTS, NEW_POST } from './types';

   export const fetchPosts = () => dispatch => {
     fetch('https://jsonplaceholder.typicode.com/posts')
       .then(res => res.json())
       .then(posts =>
         dispatch({
           type: FETCH_POSTS,
           payload: posts
         })
       );
   };

   export const createPost = postData => dispatch => {
     fetch('https://jsonplaceholder.typicode.com/posts', {
       method: 'POST',
       headers: {
         'content-type': 'application/json'
       },
       body: JSON.stringify(postData)
     })
       .then(res => res.json())
       .then(post =>
         dispatch({
           type: NEW_POST,
           payload: post
         })
       );
   };
Enter fullscreen mode Exit fullscreen mode

7. Create an reducer ./reducers/clientReducer.js.

   import { FETCH_POSTS, NEW_POST } from '../actions/types';

   const initialState = {
     items: [],
     item: {}
   };

   export default function(state = initialState, action) {
     switch (action.type) {
       case FETCH_POSTS:
         return {
           ...state,
           items: action.payload
         };
       case NEW_POST:
         return {
           ...state,
           item: action.payload
         };
       default:
         return state;
     }
   }
Enter fullscreen mode Exit fullscreen mode

8. Add the reducer entry in the root reducer ./reducers/index.js.

   import { combineReducers } from 'redux';
   import clientReducer from './clientReducer';

   export default combineReducers({
     posts: clientReducer
   });
Enter fullscreen mode Exit fullscreen mode

9. Use redux in components.

src/components/Post.js

   import React, { Component } from 'react';
   import PropTypes from 'prop-types';
   import { connect } from 'react-redux';
   import { fetchPosts } from '../../actions/clientActions';

   class Posts extends Component {
     componentWillMount() {
       this.props.fetchPosts();
     }

     componentWillReceiveProps(nextProps) {
       if (nextProps.newPost) {
         this.props.posts.unshift(nextProps.newPost);
       }
     }

     render() {
       const postItems = this.props.posts.map(post => (
         <div key={post.id}>
           <h3>{post.title}</h3>
           <p>{post.body}</p>
         </div>
       ));
       return (
         <div>
           <h1>Posts</h1>
           {postItems}
         </div>
       );
     }
   }

   Posts.propTypes = {
     fetchPosts: PropTypes.func.isRequired,
     posts: PropTypes.array.isRequired,
     newPost: PropTypes.object
   };

   const mapStateToProps = state => ({
     posts: state.posts.items,
     newPost: state.posts.item
   });

   export default connect(mapStateToProps, { fetchPosts })(Posts);
Enter fullscreen mode Exit fullscreen mode

src/components/PostForm.js

   import React, { Component } from 'react';
   import PropTypes from 'prop-types';
   import { connect } from 'react-redux';
   import { createPost } from '../../actions/clientActions';

   class PostForm extends Component {
     constructor(props) {
       super(props);
       this.state = {
         title: '',
         body: ''
       };

       this.onChange = this.onChange.bind(this);
       this.onSubmit = this.onSubmit.bind(this);
     }

     onChange(e) {
       this.setState({ [e.target.name]: e.target.value });
     }

     onSubmit(e) {
       e.preventDefault();

       const post = {
         title: this.state.title,
         body: this.state.body
       };

       this.props.createPost(post);
     }

     render() {
       return (
         <div>
           <h1>Add Post</h1>
           <form onSubmit={this.onSubmit}>
             <div>
               <label>Title: </label>
               <br />
               <input
                 type="text"
                 name="title"
                 onChange={this.onChange}
                 value={this.state.title}
               />
             </div>
             <br />
             <div>
               <label>Body: </label>
               <br />
               <textarea
                 name="body"
                 onChange={this.onChange}
                 value={this.state.body}
               />
             </div>
             <br />
             <button type="submit">Submit</button>
           </form>
         </div>
       );
     }
   }

   PostForm.propTypes = {
     createPost: PropTypes.func.isRequired
   };

   export default connect(null, { createPost })(PostForm);
Enter fullscreen mode Exit fullscreen mode

Update the App.js

   import React from 'react';

   import Posts from './posts/Posts';
   import PostForm from './posts/PostForm';

   import { Provider } from 'react-redux';
   import store from '../store';

   function App() {
     return (
       <Provider store={store}>
         <div>
             <PostForm />
             <hr />
             <Posts />
           </div>
       </Provider>
     );
   }

   export default App;
Enter fullscreen mode Exit fullscreen mode

If you want the code, you can find it here:

You can find me here:

See you around!

SurveyJS custom survey software

Simplify data collection in your JS app with a fully integrated form management platform. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more. Integrates with any backend system, giving you full control over your data and no user limits.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay