-
-
Save JackHowa/ead36f33879c672d8c5ed937690b654e to your computer and use it in GitHub Desktop.
this is for the free code camp course on Redux https://learn.freecodecamp.org/front-end-libraries/redux/create-a-redux-store |
https://learn.freecodecamp.org/front-end-libraries/redux/get-state-from-the-redux-store
- get ... state
- retrieve the state (that sounds better 'retrieve')
const store = Redux.createStore(
(state = 5) => state
);
// change code below this line
const currentState = store.getState();
https://learn.freecodecamp.org/front-end-libraries/redux/define-a-redux-action
- an action is just a js object that contains info about what's occurred with data
- redux is about dispatching these actions
- actions need a type property
// Define an action here:
const action = { type: 'LOGIN' };
https://learn.freecodecamp.org/front-end-libraries/redux/define-an-action-creator
- as simple as returning the obj is an action creator
An action creator is simply a JavaScript function that returns an action.
const action = {
type: 'LOGIN'
}
// Define an action creator here:
function actionCreator() {
return action;
};
https://learn.freecodecamp.org/front-end-libraries/redux/dispatch-an-action-event
- use the const with the () as the end loginAction() to return it
const store = Redux.createStore(
(state = {login: false}) => state
);
const loginAction = () => {
return {
type: 'LOGIN'
}
};
// Dispatch the action here:
store.dispatch(loginAction());
https://learn.freecodecamp.org/front-end-libraries/redux/handle-an-action-in-the-store
- used an an expression here to simplify
- basically conditional reducer based on action type
const defaultState = {
login: false
};
const reducer = (state = defaultState, action) => {
// change code below this line
return {
login: action.type === 'LOGIN',
}
// if (action.type === 'LOGIN') {
// return {
// login: true,
// }
// } else {
// return {
// login: false,
// }
// change code above this line
};
const store = Redux.createStore(reducer);
const loginAction = () => {
return {
type: 'LOGIN'
}
};
https://learn.freecodecamp.org/front-end-libraries/redux/create-a-redux-store/
redux is a state management framework
- redux state is one object
- each component can have its own local state
- redux state is the single source of truth
- createStore on the redux object
const reducer = (state = 5) => {
return state;
}
// Redux methods are available from a Redux object
// For example: Redux.createStore()
// Define the store here:
// takes in the reducer as an argument
// the the method createStore on the Redux object
// the redux store is the one source of truth
const store = Redux.createStore(reducer);
https://learn.freecodecamp.org/front-end-libraries/redux/get-state-from-the-redux-store
- retrieve the current state of the state
- next and current seem to be redux syntax
const store = Redux.createStore(
(state = 5) => state
);
// change code below this line
// this is the getter for the state
const currentState = store.getState();
https://learn.freecodecamp.org/front-end-libraries/redux/define-a-redux-action
- updating state via redux is one of the key areas of its use
// Define an action here:
// basically a bare action object
// type property is important here
const action = { type: 'LOGIN'};
https://learn.freecodecamp.org/front-end-libraries/redux/define-an-action-creator
- what about action creators vs dispatchers
const action = {
type: 'LOGIN'
}
// Define an action creator here:
// just minimal returning an action via the function
const actionCreator = () => action;
https://learn.freecodecamp.org/front-end-libraries/redux/dispatch-an-action-event
- dispatch the created action
- the store is responsible for dispatching this action
// redux store object
// with reducer as arg
const store = Redux.createStore(
(state = {login: false}) => state
);
// set the type through the action creator
// returns an action obj
const loginAction = () => {
return {
type: 'LOGIN',
}
};
// Dispatch the action here:
store.dispatch(loginAction());
- command + l for getting this url
https://superuser.com/questions/385972/how-to-select-chrome-url-address-bar-by-using-shortcuts?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
https://learn.freecodecamp.org/front-end-libraries/redux/handle-an-action-in-the-store/
A reducer takes state and action as arguments, and it always returns a new state
const defaultState = {
login: false
};
const reducer = (state = defaultState, action) => {
// change code below this line
switch (action.type) {
// look for the action.type
// the reducer seems kinda like the decider or interpreter
// for the action creator
case 'LOGIN':
return {
login: true
}
break;
default:
return state;
}
// change code above this line
};
const store = Redux.createStore(reducer);
const loginAction = () => {
return {
type: 'LOGIN'
}
};
- case statements are a standard for writing reducers in redux
- for now, with small objects, can return whole new ones
const defaultState = {
authenticated: false
};
const authReducer = (state = defaultState, action) => {
// change code below this line
switch (action.type) {
case 'LOGIN':
return { authenticated: true };
break;
case 'LOGOUT':
return { authenticated: false };
break;
default:
return state;
}
// change code above this line
};
const store = Redux.createStore(authReducer);
const loginUser = () => {
return {
type: 'LOGIN'
}
};
const logoutUser = () => {
return {
type: 'LOGOUT'
}
};
A common practice when working with Redux is to assign action types as read-only constants, then reference these constants wherever they are used.
- therefore, should maintain them as only for working with changes
- should define the types before the action creators for easy code reusability
// change code below this line
// changed here to reference before the methods
const LOGIN = 'LOGIN';
const LOGOUT = 'LOGOUT';
// change code above this line
const defaultState = {
authenticated: false
};
const authReducer = (state = defaultState, action) => {
switch (action.type) {
// changed here to reference const in reducer
case LOGIN:
return {
authenticated: true
}
// changed here to reference const in reducer
case LOGOUT:
return {
authenticated: false
}
default:
return state;
}
};
const store = Redux.createStore(authReducer);
// use const strings within the action creator
const loginUser = () => {
return {
type: LOGIN
}
};
// use const strings within the action creator
const logoutUser = () => {
return {
type: LOGOUT
}
};
https://learn.freecodecamp.org/front-end-libraries/redux/register-a-store-listener/
this is cool
- the store subscribe listener function
- this is called the store subscribe listener function
- register a store listener
const ADD = 'ADD';
const reducer = (state = 0, action) => {
switch(action.type) {
case ADD:
return state + 1;
default:
return state;
}
};
const store = Redux.createStore(reducer);
// global count variable:
let count = 0;
// change code below this line
const updateCount = () => count++;
store.subscribe(updateCount);
// change code above this line
store.dispatch({type: ADD});
console.log(count);
store.dispatch({type: ADD});
console.log(count);
store.dispatch({type: ADD});
console.log(count);
When the state of your app begins to grow more complex, it may be tempting to divide state into multiple pieces. Instead, remember the first principle of Redux: all app state is held in a single state object in the store. Therefore, Redux provides reducer composition as a solution for a complex state model. You define multiple reducers to handle different pieces of your application's state, then compose these reducers together into one root reducer. The root reducer is then passed into the Redux createStore() method.
https://learn.freecodecamp.org/front-end-libraries/redux/combine-multiple-reducers
combineReducers()
is how to manage multiple, more complex state interactions- since redux state is all one object, a root reducer can be used that's the result of the combineReducers function
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
const counterReducer = (state = 0, action) => {
switch(action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
default:
return state;
}
};
const LOGIN = 'LOGIN';
const LOGOUT = 'LOGOUT';
const authReducer = (state = {authenticated: false}, action) => {
switch(action.type) {
case LOGIN:
return {
authenticated: true
}
case LOGOUT:
return {
authenticated: false
}
default:
return state;
}
};
// this consolidates the two reducers
// the keys you give the reducers is the name of the assoc
// piece of state
const rootReducer = Redux.combineReducers({
count: counterReducer,
auth: authReducer
})
// define the root reducer here
const store = Redux.createStore(rootReducer);
https://learn.freecodecamp.org/front-end-libraries/redux/send-action-data-to-the-store/
- just look at what is in the arguments
- they're in the console
- don't look for properties that aren't there in the obj
// this defines the type value
const ADD_NOTE = 'ADD_NOTE';
// this is the reducer that takes in an action
const notesReducer = (state = 'Initial State', action) => {
switch(action.type) {
// change code below this line
case ADD_NOTE:
// weird just returning the new state
state = action.text;
return state;
break;
// change code above this line
default:
return state;
}
};
const addNoteText = (note) => {
// change code below this line
// make sure to just update text with base note
return {
type: ADD_NOTE,
text: note
}
// change code above this line
};
const store = Redux.createStore(notesReducer);
console.log(store.getState());
store.dispatch(addNoteText('Hello!'));
console.log(store.getState());
subscribe
is a method on the redux store object- that
subscribe
called every time there's an action on the store - if we dispatch to the store 3 times, then
subscribe
will be called 3 times
// this is the action name
const ADD = 'ADD';
// this is the reducer that (perhaps wrongly)
// modifies state directly
const reducer = (state = 0, action) => {
switch(action.type) {
case ADD:
// increment state by 1
return state + 1;
default:
// default returns unchanged state
return state;
}
};
// store created with reducer as arg
const store = Redux.createStore(reducer);
// this count variable will change
// global count variable:
let count = 0;
// change code below this line
// so want to reflect state changes here
// with count
// increments the value, then evaluates and stores it.
// which is better than:
// x++ evaluates the value, then increments and stores it.
// anywho... redux
store.subscribe(() => ++count)
// change code above this line
store.dispatch({type: ADD});
console.log(count);
store.dispatch({type: ADD});
console.log(count);
store.dispatch({type: ADD});
console.log(count);
++x > x++
via https://stackoverflow.com/questions/3469885/somevariable-vs-somevariable-in-javascript
for performance and make sure that alert(1++) returns 2
-
don't want to divide state into mutiple pieces when things get complex
-
first principle of redux: all app state is held in store object
-
multiple reducers for multiple pieces of state
-
can use keys for when the reducers are combined
const rootReducer = Redux.combineReducers({
auth: authenticationReducer,
notes: notesReducer
});
- the state held in the redux store will have different properties
auth
andnotes
https://learn.freecodecamp.org/front-end-libraries/redux/combine-multiple-reducers
- need to use the object syntax
- used the function references, not calling them, via
functionName
notfunctionName()
// two redux action names
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// one reducer for counter
// interesting how the reducer consts are right near it
const counterReducer = (state = 0, action) => {
switch(action.type) {
case INCREMENT:
return state + 1;
case DECREMENT:
return state - 1;
default:
return state;
}
};
const LOGIN = 'LOGIN';
const LOGOUT = 'LOGOUT';
const authReducer = (state = {authenticated: false}, action) => {
switch(action.type) {
case LOGIN:
return {
authenticated: true
}
case LOGOUT:
return {
authenticated: false
}
default:
return state;
}
};
const rootReducer = Redux.combineReducers({
count: counterReducer,
auth: authReducer,
});
const store = Redux.createStore(rootReducer);
https://learn.freecodecamp.org/front-end-libraries/redux/send-action-data-to-the-store
- can get the initial state to compare it the new state
// action's type value
const ADD_NOTE = 'ADD_NOTE';
const notesReducer = (state = 'Initial State', action) => {
switch (action.type) {
// change code below this line
// just taking away from the action
// text property to the store
case (ADD_NOTE):
return action.text;
// change code above this line
default:
return state;
}
};
// action creator
const addNoteText = (note) => {
// change code below this line
return { type: ADD_NOTE, text: note };
// change code above this line
};
const store = Redux.createStore(notesReducer);
console.log(store.getState());
// logs Initial State
// dispatch the action creator's object
store.dispatch(addNoteText('Hello!'));
// get the new state after dispatching
// to the reducer
console.log(store.getState());
// logs 'Hello!'
- redux thunk is middleware designed for async actions
- async actions are an unavoidable part of web dev
https://gist.github.com/markerikson/ea4d0a6ce56ee479fe8b356e099f857e
const REQUESTING_DATA = 'REQUESTING_DATA'
const RECEIVED_DATA = 'RECEIVED_DATA'
const requestingData = () => { return {type: REQUESTING_DATA} }
const receivedData = (data) => { return {type: RECEIVED_DATA, users: data.users} }
const handleAsync = () => {
return function(dispatch) {
// dispatch request action here
dispatch(requestingData());
setTimeout(function() {
let data = {
users: ['Jeff', 'William', 'Alice']
}
// dispatch received data action here
dispatch(receivedData(data));
}, 2500);
}
};
const defaultState = {
fetching: false,
users: []
};
const asyncDataReducer = (state = defaultState, action) => {
switch(action.type) {
case REQUESTING_DATA:
return {
fetching: true,
users: []
}
case RECEIVED_DATA:
return {
fetching: false,
users: action.users
}
default:
return state;
}
};
const store = Redux.createStore(
asyncDataReducer,
Redux.applyMiddleware(ReduxThunk.default)
);
https://learn.freecodecamp.org/front-end-libraries/redux/write-a-counter-with-redux
- need to return the whole action creator
- need to initialize a default state to get it going
// define a constant for increment action types
const INCREMENT = 'INCREMEMENT';
// define a constant for decrement action types
const DECREMENT = 'DECREMENT';
// define the counter reducer which will increment or decrement the state based on the action it receives
const counterReducer = (state = 0, action) => {
switch (action.type) {
case (INCREMENT):
return ++state;
case (DECREMENT):
return --state;
default:
return state;
}
};
// define an action creator for incrementing
const incAction = () => {return {type: INCREMENT}};
// define an action creator for decrementing
const decAction = () => {return {type: DECREMENT}};
// define the Redux store here, passing in your reducers
const store = Redux.createStore(counterReducer);
https://learn.freecodecamp.org/front-end-libraries/redux/never-mutate-state
Immutable state means that you never modify state directly, instead, you return a new copy of state.
This immutability, in fact, is what provides such features as time-travel debugging that you may have heard about.
// define action type constant
const ADD_TO_DO = 'ADD_TO_DO';
// A list of strings representing tasks to do:
const todos = [
'Go to the store',
'Clean the house',
'Cook dinner',
'Learn to code',
];
const immutableReducer = (state = todos, action) => {
switch(action.type) {
case ADD_TO_DO:
// don't mutate state here or the tests will fail
// return all the todos spread
// with the new action.todo
return [...todos, action.todo];
default:
return state;
}
};
// an example todo argument would be 'Learn React',
const addToDo = (todo) => {
return {
type: ADD_TO_DO,
// nice tricky es6 object assignment
todo
}
}
const store = Redux.createStore(immutableReducer);
https://learn.freecodecamp.org/front-end-libraries/redux/remove-an-item-from-an-array
- need to remove an item without slice
- nope:
let newState = state.slice(action.index);
https://stackoverflow.com/questions/34582678/is-this-the-correct-way-to-delete-an-item-using-redux
- fitler returns a new arr
const immutableReducer = (state = [0,1,2,3,4,5], action) => {
switch(action.type) {
case 'REMOVE_ITEM':
// don't mutate state here or the tests will fail
let newState = state.filter((element, index) => {
return index !== action.index
})
console.log(newState);
return newState
default:
return state;
}
};
const removeItem = (index) => {
return {
type: 'REMOVE_ITEM',
index
}
}
const store = Redux.createStore(immutableReducer);
https://learn.freecodecamp.org/front-end-libraries/redux/copy-an-object-with-object-assign
const newObject = Object.assign({}, obj1, obj2);
This creates newObject as a new object, which contains the properties that currently exist in obj1 and obj2.
- basically edit the properties mentioned
- doesn't mutate
const defaultState = {
user: 'CamperBot',
status: 'offline',
friends: '732,982',
community: 'freeCodeCamp'
};
undefined
console.log(Object.assign({}, defaultState, {status: 'online'}))
{user: "CamperBot", status: "online", friends: "732,982", community: "freeCodeCamp"}
const defaultState = {
user: 'CamperBot',
status: 'offline',
friends: '732,982',
community: 'freeCodeCamp'
};
const immutableReducer = (state = defaultState, action) => {
switch(action.type) {
case 'ONLINE':
// don't mutate state here or the tests will fail
return Object.assign({}, defaultState, {status: 'online'});
default:
return state;
}
};
const wakeUp = () => {
return {
type: 'ONLINE'
}
};
const store = Redux.createStore(immutableReducer);
https://learn.freecodecamp.org/front-end-libraries/redux/create-a-redux-store