You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Constants, Action Creators (sync), Reducers, and Action Creators (async)
/* -------------------< ACTIONS >--------------------- */
const MY_ACTION = 'MY_ACTION';
/* ---------------< ACTION CREATORS >------------------- */
// we export here if we're not using thunk, as these are sync action creators
export const actionCreator = (payload) => {
return {
type: 'MY_ACTION',
payload
};
};
/* -------------------< REDUCERS >--------------------- */
// we export here to supply our reducers to the store
// this is where we set initial state. accessible in components through this.props.reducerName.property
let initialState = { property1: [], property2: {} };
export default function (state = initialState, action) {
switch (action.type) {
case MY_ACTION:
return Object.assign({}, state, {property1: action.payload});
default:
return state;
}
}
/* ------------------< DISPATCHERS >-------------------- */
// these are async action creators, enabled with thunk
// otherwise, redux should dispatch from within container using the sync action creator
import axios from 'axios';
export const asyncActionCreator = (param) => dispatch => {
axios.get(`/api/backend/${param}`)
.then(res => res.data)
.then(thingWeGetBack => dispatch(actionCreator(thingWeGetBack)))
.catch(err => console.error('dang, we hit an error..!', err));
}
Components and Containers
/* --------------< PRESENTATIONAL COMPONENT >------------- */
// assumes combineReducers; otherwise use props.property instead of props.reducerName.properties
import React from 'react';
const PresentationalComponent = (props) => {
return (
<div>
{
props.reducerName.properties.map(property => {
return // always remember to return!
(
<div key={property.id}> {property.name} </div>
)
})
}
</div>
)
}
/* ---------------< STATEFUL COMPONENT >------------------ */
// assumes combineReducers; otherwise use this.props.property
// allows us to manage state and access lifecycle hooks
// REMEMBER TO BIND YOUR FUNCTIONS!
import React from 'react';
class StatefulComponent extends React.Component {
constructor (props) {
super(props);
this.state = {key: value}
this.rememberToBindYourFunctions = this.rememberToBindYourFunctions.bind(this)
}
ComponentDidMount() {
}
methodThatChangesState (newValue) {
this.setState({property: newValue});
}
render () {
return (
<div>
{this.props.reducerName.property}
<ChildComponent Method={this.rememberToBindYourFunctions} />
</div>
)
}
}
/* -------------------< CONTAINER >-------------------- */
import { connect } from 'react-redux';
// ES6 syntactic sugar!!
const mapState = ({ propertyNameOrReducerName }) => ({ propertyNameOrReducerName });
// if we need a sync dispatch:
import { loadPuppies } from './actionCreatorsFile';
const mapDispatch = (dispatch) => {
return {
methodToDispatch: (params) => dispatch(syncActionCreator(params))
}
};
// if we have all async thunk dispatchers
const mapDispatch = ({ methodToDispatch }); // react-redux specific syntactic sugar, enabled by thunk
export default connect(mapState, mapDispatch)(ComponentToReduxify);
Store and Index.js
/* --------------------< THE STORE >----------------------- */
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './redux';
export default createStore(
rootReducer,
applyMiddleware(thunk)
);
/* -------------------< browser/INDEX.js >--------------------- */
// react-redux implementation with react-router
// alternatively, put the react-redux store and ReactDOM.render into a higher level file
'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import { browserHistory, Router, Route, IndexRedirect } from 'react-router';
import { Provider } from 'react-redux';
import store from './store';
import Container from './containers/Container';
import { onLoadFunction } from './redux/actionCreator';
const fetchInitialData = (nextRouterState, replace, done) => {
store.dispatch(actionCreatorAction(nextRouterState.params.id));
}
ReactDOM.render(
<Provider store={ store }>
<Router history={ browserHistory }>
<Route path="/" onEnter={ fetchInitialData }>
<IndexRedirect to="/defaultURI" />
<Route path="/path" component={ Components } />
<Route path="/path/:id" component={ SingleComponent } onEnter={ doSomething } />
</Route>
</Router>
</Provider>,
document.getElementById('app')
);
Extra Stuff
Combining Reducers
/* ---------------< COMBINING REDUCERS >-------------------- */
import { combineReducers } from 'redux';
import newReducer from './newReducer';
import anotherReducer from './anotherReducer';
export default combineReducers({ newReducer, anotherReducer });