to
Redux
(Without React)
Define what redux is
Describe actions and reducers in redux
Describe methods on the redux store
A plain JavaScript object that must have a key called type and a string value
{
type: "LOGOUT_USER"
}
The action can have any number of additional keys
A function that accepts the state and an action and returns a new state (entire state object)
function rootReducer(state={}, action) {
switch(action.type) {
case "LOGOUT_USER":
return {...state, login: false}
case "LOGIN_USER":
return {...state, login: true}
default:
return state;
}
}
Use the Redux createStore function which accepts the root reducer as a paramter
const store = Redux.createStore(rootReducer);
The only way to change the state is by calling dispatch
const store = Redux.createStore(rootReducer);
store.dispatch({
type: "LOGIN_USER"
});
You can get the state of the Redux store using getState
const store = Redux.createStore(rootReducer);
store.dispatch({
type: "LOGIN_USER"
});
const newState = store.getState();
You can add a listener to see when the state has changed
const store = Redux.createStore(rootReducer);
const changeCallback = () => {
console.log("State has changed",
store.getState());
}
const unsubscribe =
store.listen(changeCallback);
Redux State Change
Describe react-redux
Use the provider component to share a store
Use connect to mapStateToProps and mapDispatchToProps
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
import React from 'react';
import {connect} from 'react-redux';
const BoldName = ({name}) => (
<strong>{name}</strong>
);
const mapStateToProps = state => (
{ name: state.name }
);
export default
connect(mapStateToProps, null)(BoldName);
import React from 'react';
import {connect} from 'react-redux';
const DelName = ({delName}) => (
<button type="button"
onClick={delName}>DELETE</button>
);
const mapDispatchToProps = (
dispatch, ownProps
) => (
{
delName: () => (dispatch({
type: "DEL_NAME"
}))
}
);
export default
connect(null, mapDispatchToProps)(DelName);
import React from 'react';
import BoldName from './BoldName';
import DelName from './DelName';
const App = () => (
<div>
<BoldName />
<DelName />
</div>
);
Define a presentational component vs a container component
Define combine reducers
Define action creators
Describe a folder structure for redux
import {combineReducers} from 'redux';
import currentUser from './currentUser';
import messages from './messages';
const rootReducer = combineReducers({
currentUser,
messages,
});
export default rootReducer;
combineReducers
const messages = (state=[], action) => {
switch(action.type) {
case "LOAD_MESSAGES":
return [...action.messages];
case "ADD_MESSAGE":
return [action.message, ...state];
default:
return state;
}
};
export default messages;
Messages Reducer
Action Creators
const mapDispatchToProps = dispatch => ({
onLogout() {
dispatch({
type: "USER_LOGOUT"
})
},
});
const mapDispatchToProps = dispatch => ({
onLogout() {
dispatch(actions.userLogout())
},
});
Define redux middleware
Define redux thunk and show a use case
import { createStore,
applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { createLogger } from 'redux-logger'
import reducer from './reducers'
const middleware = [ thunk ]
if (process.env.NODE_ENV !== 'production') {
middleware.push(createLogger())
}
const store = createStore(
reducer,
applyMiddleware(...middleware)
)
export const receivePosts = (reddit, json) => ({
type: RECEIVE_POSTS,
reddit,
posts: json.data.children.map(child => child.data),
receivedAt: Date.now()
}
const fetchPosts = reddit => (
dispatch => {
dispatch(requestPosts(reddit))
return fetch(`https://www.reddit.com/r/${reddit}.json`)
.then(response => response.json())
.then(json => dispatch(receivePosts(reddit, json)))
}
)