Install redux
npm install react-redux
Add redux to index.js file
React Redux provides <Provider/>, which makes the Redux store available to the rest of your app
import React from 'react' import ReactDOM from 'react-dom' import thunk from 'redux-thunk' import {createStore, applyMiddleware} from 'redux' import { Provider } from 'react-redux' import store from './store' import allReducers from './redux/reducers/allReducer.js' import App from './App' const rootElement = document.getElementById('root') ReactDOM.render( <Provider store={createStore(allReducers, applyMiddleware(thunk))}> <App /> </Provider>, rootElement )
Connect Component to store
React Redux provides a connect function for you to connect your component to the store.
import React, { Component } from 'react'; import { connect } from 'react-redux'; import LandingPage from './landing_page'; import Header from './header/header'; import Posts from './post/posts'; import LeftPanel from './left_panel'; import RightPanel from './right_panel'; class Home extends Component { constructor(props) { super(props); this.state = { userAuthenticated: localStorage.getItem('userUuid') ? true : false } } componentDidMount() { } render() { return ( <div> <Header /> <main> <div className="main-wrapper pt-80"> <div className="container"> <div className="row"> <LeftPanel page="HOME"/> <Posts page="HOME"/> <RightPanel/> </div> </div> </div> </main> </div> ) } } const mapStateToProps = (state) => { return state; } export default connect(mapStateToProps, { })(Home);
Access data from the store
import React, { Component } from 'react'; import {connect} from 'react-redux'; import { loadNotifications } from '../redux/actions/NotificationAction'; class RecentNotifications extends Component { constructor(props) { super(props); console.log("RecentNotifications constructor()"); this.state = { } } componentDidMount(){ } render() { console.log("RecentNotifications render()"); console.log(this.props.ntcsState.notificationInfo.content); let listOfNotifications = {}; if(this.props.ntcsState.notificationInfo.content!==undefined && this.props.ntcsState.notificationInfo.content!==null){ listOfNotifications = this.props.ntcsState.notificationInfo.content.map((notification) => <li key={notification.uuid} className="unorder-list"> {/* profile picture end */} <div className="profile-thumb"> <a href="/"> <div className="profile-thumb-small"> <img src={notification.createdBy.profileImageUrl} alt="profile" /> </div> </a> </div> {/* profile picture end */} <div className="unorder-list-info"> <h3 className="list-title"><a href="/">Any one can join with us if you want</a></h3> <p className="list-subtitle">5 min ago</p> </div> </li> ); }else{ listOfNotifications = <li className="unorder-list"></li> } return ( <div className="card widget-item"> <h4 className="widget-title">Recent Notifications</h4> <div className="widget-body"> <ul className="like-page-list-wrapper"> {listOfNotifications} </ul> </div> </div> ) } } const mapStateToProps = (state) => { return state; } export default connect(mapStateToProps,{ loadNotifications: loadNotifications })(RecentNotifications);
You can access data from the store by connecting to the store and using props like this.props.ntcsState.
NotificationReducer.js
const notificationInitialState = { notificationInfo: {} }; let notificationInfo; export const NotificationStateReducer = (state = notificationInitialState, action) => { switch (action.type) { case 'LOAD_NOTIFICATIONS': notificationInfo = action.payload; //console.log("LOAD_NOTIFICATIONS"); //console.log(notificationInfo.data); return Object.assign({}, state, { notificationInfo: notificationInfo.data }); default: return state; } }
NotificationAction.js
import NotificationAPI from '../../api/notification'; export const loadNotifications = () => { let userUuid = localStorage.getItem("userUuid"); let pageSize = 10; let pageNumber = 0; //console.log("LOAD_NOTIFICATIONS"); return async function(dispatch, getState) { const response = await NotificationAPI.getNotifications(userUuid, pageSize, pageNumber); dispatch({ type: "LOAD_NOTIFICATIONS", payload: response }); }; };
Trigger actions in the store
import React, { Component } from 'react'; import Avatar from '../images/avatar.png'; import UserAPI from '../api/user'; import { connect } from 'react-redux'; import { setUserSession } from '../redux/actions/UserAction'; class ProfileUpdate extends Component { constructor(props) { super(props); this.state = { profile: { firstName: "", lastName: "", email:"", phoneNumber:"", gender: "", maritalStatus: "", profileImageUrl: props.userState.userProfileImageUrl!== null ? props.userState.userProfileImageUrl : Avatar, coverImageUrl: props.userState.userCoverImageUrl!== null ? props.userState.userCoverImageUrl : Avatar, uploadImage:"" } } this.loadProfile = this.loadProfile.bind(this); this.handleInputChange = this.handleInputChange.bind(this); this.updateProfile = this.updateProfile.bind(this); } componentDidMount() { } handleInputChange(event) { console.log("handleInputChange"); const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; if(name==="profileImageFile"){ console.log("upload profile image"); const formData = new FormData(); formData.append( "file", event.target.files[0], event.target.files[0].name ); let uuid = localStorage.getItem("userUuid"); UserAPI.uploadProfileImage(uuid, formData) .then(response => { console.log("response"); console.log(response.data); let user = response.data; this.setState({profile:user},()=>{}); this.props.setUserSession(user); }).catch(error => { console.log("error"); console.log(error.response.data); }); return; } if(name==="coverImageFile"){ console.log("upload cover image"); const formData = new FormData(); formData.append( "file", event.target.files[0], event.target.files[0].name ); let uuid = localStorage.getItem("userUuid"); UserAPI.uploadCoverImage(uuid, formData) .then(response => { console.log("response"); console.log(response.data); let user = response.data; this.setState({profile:user},()=>{}); this.props.setUserSession(user); }).catch(error => { console.log("error"); console.log(error.response.data); }); return; } let updatedState = { profile: this.state.profile } updatedState['profile'][name] = value; console.log("updated state"); console.log(updatedState); this.setState(updatedState, function () { //console.log(this.state); }); } loadProfile(event){ let uuid = localStorage.getItem("userUuid"); UserAPI.getProfile(uuid) .then(response => { console.log("response"); console.log(response.data); let user = response.data; this.setState({profile: user}); this.props.setUserSession(user); }).catch(error => { console.log("error"); console.log(error.response.data); }); } updateProfile(event){ console.log(this.state.profile); UserAPI.updateProfile(this.state.profile) .then(response => { console.log("response"); console.log(response.data); let user = response.data; this.setState({profile: user}); this.props.setUserSession(user); }).catch(error => { console.log("error"); console.log(error.response.data); }); } render() { return ( <div className="col-lg-2 col-md-3 d-none d-md-block"> <div className="profile-edit-panel"> <button onClick={this.loadProfile} className="btn-adda edit-btn" data-toggle="modal" data-target="#profileUpdateModal" >edit profile</button> </div> <div className="modal fade in" id="profileUpdateModal" aria-labelledby="profileUpdateModal"> <div className="modal-dialog"> <div className="modal-content"> <div className="modal-header"> <h5 className="modal-title">Update Profile</h5> <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> </div> <div className="modal-body custom-scroll"> <div className="row"> <div className="col-sm-12 text-center"> <img src={this.state.profile.profileImageUrl} className="rounded" alt="..."/> </div> </div> <div className="row"> <div className="col-sm-6 offset-sm-3"> <div className="form-group text-center"> <input type="file" className="form-control-file" name="profileImageFile" onChange={this.handleInputChange} /> </div> </div> </div> <div className="row"> <div className="col-sm-12 text-center"> <img src={this.state.profile.coverImageUrl} className="rounded" alt="..."/> </div> </div> <div className="row"> <div className="col-sm-6 offset-sm-3"> <div className="form-group text-center"> <input type="file" className="form-control-file" name="coverImageFile" onChange={this.handleInputChange} /> </div> </div> </div> <div className="row"> <div className="col-sm-6"> <div className="form-group"> <label>First Name</label> <input type="text" className="form-control" aria-describedby="firstNameHelp" placeholder="Enter first name" name="firstName" onChange={this.handleInputChange} value={this.state.profile.firstName}/> </div> </div> <div className="col-sm-6"> <div className="form-group"> <label>Last Name</label> <input type="text" className="form-control" aria-describedby="lastNameHelp" placeholder="Enter last name" name="lastName" onChange={this.handleInputChange} value={this.state.profile.lastName} /> </div> </div> </div> <div className="row"> <div className="col-sm-6"> <div className="form-group"> <label>Email</label> <input type="email" className="form-control" aria-describedby="emailHelp" placeholder="Enter email" name="email" onChange={this.handleInputChange} value={this.state.profile.email} /> </div> </div> <div className="col-sm-6"> <div className="form-group"> <label>Phone</label> <input type="tel" className="form-control" aria-describedby="phoneNumberHelp" placeholder="Enter phone number" name="phoneNumber" onChange={this.handleInputChange} value={this.state.profile.phoneNumber} /> </div> </div> </div> <div className="row"> <div className="col-sm-6"> <div className="form-group"> <label>Gender</label> <select className="form-control" name="gender" onChange={this.handleInputChange} value={this.state.profile.gender}> <option value="MALE">Male</option> <option value="FEMALE">Female</option> <option value="TRANGENDER">Transgender</option> </select> </div> </div> <div className="col-sm-6"> <div className="form-group"> <label>Marital Status</label> <select className="form-control" name="maritalStatus" onChange={this.handleInputChange} value={this.state.profile.maritalStatus}> <option value="SINGLE">Single</option> <option value="MARRIED">Married</option> </select> </div> </div> </div> </div> <div className="modal-footer"> <button type="button" className="btn-adda post-share-btn" data-dismiss="modal">cancel</button> <button onClick={this.updateProfile} type="button" data-dismiss="modal" className="btn-adda post-share-btn">Update</button> </div> </div> </div> </div> </div> ) } } const mapStateToProps = (state) => { //console.log("home all states", state) return state; } export default connect(mapStateToProps, { setUserSession: setUserSession })(ProfileUpdate);
You use props to call actions like this
this.props.setUserSession(user);