Skip to content

Instantly share code, notes, and snippets.

@JackHowa
Last active May 22, 2022 17:49
Show Gist options
  • Save JackHowa/ead36f33879c672d8c5ed937690b654e to your computer and use it in GitHub Desktop.
Save JackHowa/ead36f33879c672d8c5ed937690b654e to your computer and use it in GitHub Desktop.
fcc redux curriculum snippets
this is for the free code camp course on Redux https://learn.freecodecamp.org/front-end-libraries/redux/create-a-redux-store
@JackHowa
Copy link
Author

JackHowa commented Jun 4, 2018

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.

@JackHowa
Copy link
Author

JackHowa commented Jun 4, 2018

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);
 

@JackHowa
Copy link
Author

JackHowa commented Jun 4, 2018

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());

@JackHowa
Copy link
Author

  • 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);

@JackHowa
Copy link
Author

++x > x++ via https://stackoverflow.com/questions/3469885/somevariable-vs-somevariable-in-javascript

for performance and make sure that alert(1++) returns 2

@JackHowa
Copy link
Author

  • 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
});

@JackHowa
Copy link
Author

  • the state held in the redux store will have different properties auth and notes

@JackHowa
Copy link
Author

JackHowa commented Jun 16, 2018

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 not functionName()
// 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);

@JackHowa
Copy link
Author

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!'

@JackHowa
Copy link
Author

https://learn.freecodecamp.org/front-end-libraries/redux/use-middleware-to-handle-asynchronous-actions

  • 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)
);

@JackHowa
Copy link
Author

JackHowa commented Jun 17, 2018

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); 

@JackHowa
Copy link
Author

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);

@JackHowa
Copy link
Author

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);

@JackHowa
Copy link
Author

JackHowa commented Jun 17, 2018

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);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment