Skip to content

Instantly share code, notes, and snippets.

@Theartbug
Last active April 23, 2018 21:57
Show Gist options
  • Save Theartbug/92a0f4e5133c1cc68c1293b33bf759f9 to your computer and use it in GitHub Desktop.
Save Theartbug/92a0f4e5133c1cc68c1293b33bf759f9 to your computer and use it in GitHub Desktop.
The second half of bootcamp (react / redux)

Christine LaPorte Talk: Career Coach

Keys to getting a job:

  • Brand passion
    • research
  • Internal ally
    • best use of time
    • network hard, coffee
  • not job postings
    • can give a clue
  • placement agency
    • can be black listed if double submitted at agency
    • sometimes they may have keys to the job door with a client

Resume:

  • 1 page
  • where have I added value
    • success metric
  • carbon copy to job you are applying to, same language
  • partner with a writer

Networking:

  • design week
    • go to open houses with the goal of making a coffee date
    • sign up for events as they fill up
  • Go to networking events
    • Add speakers, hosts, and send note on linkedin
      • "hey I see you are hosting / speaking at .... I look forward to seeing you there / meeting you"
    • write down / keep track of their information
    • go to the event and try to meet them in person
    • tell them your wants and needs
      • I am a front-end javascript dev looking for work in ....
    • grab business card and go home and add them on linkedin
    • add them to tracking information
  • connect by finding them on twitter / social media and a physical letter / note
    • "hello ... I am excited to talk to you about your experience in... and would love to take you to coffee on these dates at these places?"
  • informational interview
    • don't come off as "I don't want this job, I need a job"
    • look at their linkedin
    • look at company website
    • look at news tab in google
    • have them talk about themselves
    • send meeting request for calendar invite
      • say "psyched to see you tomorrow" (check in)
    • company culture, turn over, projects they are working on
    • how can you contribute?
    • ask for feedback on github, what would make me a stronger candidate for this job?
    • ask "Hey is it okay if I reach out to HR and mention we had this meeting?" for name drop
    • end with an offer
      • Can I volunteer at your next event?
    • ask "what is the compensation range I should be asking for in interviews"
      • "I have a strict non-disclosure agreement with prior employer. I'd like to ask if there is a range"
      • "right now I'm having conversations about opportunities in the 68k range"
  • nurture network
    • send out cards, checking in, care!
    • even if full time employment, keep it up as it is false safety
    • "hey I'm heading to the ... event, want to meet there?"
    • "I would love to contribute to your team"

When in job:

  • track success metrics while in job! Push for compensation increase and title change. Ask for your worth.
  • be candid about opportunities "I appreciate the offer but I am also negotiating with my company"
  • "I really want to be here, but I have an offer of $x, can you match or beat it?"

Apex Systems Presentation:

Speaker: Richard Stanley

Networking directly and showing code to those who have jobs in industry

  • referrals are important and lead to jobs

Personal projects

  • ask yourself about something that you need or want and build it (search that looks for open source projects that need help on github)
  • search by expertise in projects

Social media

  • follow on slack, twitter, and stack overflow
  • Portland devs prefer twitter?
  • offering help on Stack overflow?
  • slack
    • frontend developer
    • look for software to contribute to and ask to join slack

Meetups

  • calagator
  • PDX women in tech
  • PASS (SQL)
  • Javascript
    • PDXNG
    • NodeJS
    • DoughnutJS
  • Project Management Institute (PMI)

Linkedin

  • curate network
  • only add people you know
  • don't add recruiters unless you've talked to them at least on the phone

Resume

  • keep it at one page
  • give a longer one if they ask for one
  • "things i've done in my spare time"
  • by project, say what YOU did, not what is in the project
  • volunteer work, internships, github projects, freelance work, education, personal website, hackathons, certs / bootcamps, linkedin profile, skills (for ATS)
  • order skills at top if they are all stuff you can talk to, place at bottom if it's just for ATS

Job sites

  • indeed
  • monster (bad, but get calls)
  • dice
  • apex Systems (will not call you unless you are a good fit)
  • careerbuilder (bad, but get calls)
  • stackoverflow

Applicant Tracking Systems

  • keyword matching
  • filters out resumes
  • jobscan.co/promo/apex

How to work with recruiters

  • staffing firms
    • work for clients to find employees for client
  • corporate
    • work for the company to find talent
  • consulting firms
    • often contracting positions
    • bring in talent for a particular project
    • leave when project is done

Recruiters

  • resume reviews, mock interviews, market trends, keep in touch
    • get a phone call once every 3-6 months
  • proactive submissions
    • send resume to places that aren't even hiring, but positions will sometimes be made for you if you are good enough
  • pipelines
    • work closely with one or two recruiters and build a relationship
  • if they don't spend time on these things, move on

Pleuralsite

  • subscription website for continued education
  • download on phone listen to like podcast

After first job

  • stay in job for at least a year and move on, especially for wage increase
  • find some niche new technology and learn it, make $$
  • inflation is 6%, usually only get raises that are 5% at best. Leave!
  • 5 years is average time to be at a job

Negotiation

  • with recruiters: can negotiate more cash
    • ask for 10% above what they say they can give, if no budge wait until next day and go a little lower
    • small locale firms give you bigger push
    • pitch recruiters against one another
    • recruiters only get paid during length of contract
  • with company directly: can negotiate more benefits
    • costs them less than actually pay more
    • more PTO, continued learning, parking, transit, flexible hours
    • weaker negotiation space
    • "what is this position looking to pay?"

Interviews

  • closely typed vs loosely typed
  • polymorphism
  • book: Design patterns: Elements of reusable object-oriented software
    • talking shop with patterns
    • talking in terms of concepts

Creative Staffing Agencies: 52LTD: 52ltd.com Aquent/VitaminT: https://vitamintalent.com/ Mathys Potestio: http://mathys-potestio.com/ 24|Seven: https://www.24seventalent.com/en-us/home

Tech Staffing Agencies: Apex: https://www.apexsystems.com/Pages/default.aspx CorSource: http://www.corsource.com/ KForce: https://www.kforce.com/ Vanderhouwen: http://www.vanderhouwen.com/

Day 18: Adding user auth

Testing actions with Firebase

  • Create firebase .on('value') event listener that will dispatch an action for every value change for the listener

  • have the .on('value') and data.val() separate from the action for the listener so it is easier to mock. These can live inside the firebase api in a function that becomes a service call

  • you can try to mock.on('value') but it is less fun

  • ongoing action creators need to be kept from being recalled

    • keep in app so it is only loaded once
      • not the best since app owns stuff that should belong to other components
    • keep track of listening true / false in action creator
    let listening = false;
    
    export function action() {
      if(listening) return;
      listening = true; // changes it after the first call
    }
    
  • firebase gives back an object but we will usually want an array to iterate over in creation of VDOM elements. This also allows us to add a key property that is the firebase key for that item.

  • utilize firebase verbage in actions setNoun, getNoun

User Auth

  • auth.onAuthStateChanged will fire when there is a user state change.
  • create an action that listens for a user in high level component (App)
    • must be a thunk
  • have a reducer that sets the new user

actions:

export function listenForUser() {
  return dispatch => {
      auth.onAuthStateChanged(user => {
        dispatch({
          type: USER,
          payload: user
        })
    }
  }
}
  • firebase Auth does come with a pre-rolled auth UI
    • npm i firebase UI
    • add style-sheets in index.html that come with the UI
    • comes with success callbacks
    • go into firebase console Auth and turn on sign in methods desired
    • place into component const ui = firebaseui.auth.authUI(firebase.auth())
    • turn off credential helper as it is annoying
  • create components for sign up / sign in / sign out
  • the way that firebase works, some actions will be listeners on changes in firebase, so actions for making changes in the app that affect firebase may not always be needed as long as a listener already exists
    • listenForUser
  • after a user is successful in creating an account, redirect them back to where they came from

Private Routes

  • will handle if there no user, send them to the login page
    • include a state.from property to go back to wherever the user was
    • can be found in this.props.location.state.from
  • use in-leu of the <Route> tag from Router use <PriaveRoute>

Day 17: Adding firebase

random notes

  • in a switch statement, if cases do the same thing, you can stack them:
switch(type) {
  case END_GAME: //will flow to the next case
  case NEW_GAME:
    return null;
}

firebase REST API

  • when fetching to a RESTFUL API with firebase, you can use URL/${something}.json to obtain a JSON object of the data
  • if you store data with a number in firebase, it infers you are organizing an array and will return null for the 0 position
  • npm i firebase to link the dependency
  • get and post will work with the app
  • firebase will return an object from a requested node. Do Object.keys to turn it into an array to iterate over
  • will not be able to sort results returned, will have to do on the front end

Day 16: React Transition Group & general react questions

React Checklist

  1. store.js
  • import createStore, combineReducers, composeEnhancers, applyMiddleware
  • import reducers
  • combine those reducers
  • call createStore
    • pass in "combined" root reducer
    • use composeEnhancers and applyMiddleware to include all needed middleware plus make REDUX_DEV_TOOLS word
      • thunk
        • you need access to getStore
        • you need to make multiple calls to dispatch
        • async, if not fitting into promiseMiddleware
      • promiseMiddleware
        • want action creators to be simple and pass a promise as the payload
    • can give preset data so presentation components have some data to work with
    • export store
  1. index.js
  • import Provider from react-redux
  • import store
  • wrap app component in <Provider store={store}></Provider>
  1. Create reducers by features in various component folders
  • export named function per data that needs to be in the store
  1. Create action creators by feature
  2. use connect to:
  • inject parts of the store state as props into component
    • mapStateToProps
      • there is a second parameter in mapStateToProps that allows parent props to be passed in
    • mapDispatchToProps
      • ``(dispatch) => { //return object of props (which are functions) to inject}
      • can leverage bindActionCreators built in by passing an object ``{ actionCreator1, actionCreator2 }
    • sometimes can use mergeProps third parameter to do more
    • pass null to a parameter if don't need a piece of connect
export default connect(
  ({ commentsByNote}, {id}) => {
    comments = commentsByNote(id)
  }),
  ({ actions }),
  ({ nameSomeProps}) => { merge them })

thunk testing

it('resolves a thunk', () => {
  const index = 0;
  const selection = 'rock';

  const result = makeChoice(0, 'rock');
  const dispatch = jest.fn();
  const getState = jest.fn(() => ({selections:[]}));
  result(dispatch, getState);
  expect(dispatch).toBeCalledWith({
    type: SELECT,
    payload: { index, selection}
  })
  expect(dispatch.mock.calls.length).toBe(1);
  expect(getState).toBeCalled();

});

children components

  • when components are passed as children inside of other components, a property called this.children is accessible within the parent component
  • you can also pass in a function this way, though it is preferred to pass it as a prop with render prop for consistency
<Parent stuff={stuff}>
  <div>{child}</div>
</Parent>
  • sometimes you will need to access the DOM node itself
    • Ex: have an input box auto-focused on load
  • use can do the same with a component, though less common
componentDidMount() {
  this.nameInput.focus();
}
<input ref={node => this.nameInput} = node/>

ReactCSSTransitionGroup

  • injects as a span
  • children of the transition group must have a key to differentiate itself
  • utilize class names enter and leave, but you can declare your own if you want
  • timeouts must have same value as transitions in CSS
  • opacity and transform are best preforming properties in transitions

in jsx:

<ReactCssTransitionGroup
  transitionName="fade"
  transitionEnterTimeout={500} //milliseconds
  transitionLeaveTimeout={300}>
  {thingsToTransition}
</ReactCSSTransitionGroup>

in CSS:

.example-enter {
  opacity: 0.01;
}

.example-enter.example-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}

.example-leave {
  opacity: 1;
}

.example-leave.example-leave-active {
  opacity: 0.01;
  transition: opacity 300ms ease-in;
}

Day 15: whiteboarding

Closures

function makeSayIt(total) {

  return function more(str) {
    if(!str) return total;
    total += str;
    return more;
  }
}
const sayIt = makeSayIt('');

//then call sayIt with whatever

Day 14: promises, mocking

random notes

React Router

  • can use render={() => } method on props for a Route to give specific props like match, location, history
    • can use render to pass specific functions from parent if need be
  • when using component syntax component={ComponentName}
  • match is an object with information on how a link was matched with a route
  • can bring these properties in through the connect() statement with redux, or directly into the component through this.props.match.id

with connect:

export default connect(
  (state, props) => ({ 
    users: state.users,
    albumId: props.match.params.id //brings in the album id from url
  }),
  { loadAlbum }
)(AlbumDetail);

  • cannot use unknown parameters in <Link>.
    • Ex: <Link to="/albums/${match.params.id}/books></Link>
  • withRouter wraps component to give it history context when it is not a direct descendant of the <Router></Router>
  • use history.push('new/location') to programmatically change a location, such as within a function

Jest mock

  • import the api into the test, then check to see if it was called with was you expected it to be called with. Will check if it was forgotten / missed.
import galleryApi from '../../services/galleryApi';

expect(galleryApi.add).toBeCalledWith(image);

Promises

  • always asynchronous
  • a callback
  • only happen once
  • rarely use new Promise()
    • most apis will create a Promise itself

.then( () => function stuff )

  • will take what is returned from a promise and allow you to do something with it.
  • can chain as long as each one returns something
  • smart enough to know when it is handed a promise and wait to return the value given by that promise!
  • can be chained inside of a function and still be used within another promise chain!

.catch( err => do something with err )

  • only needed once at the end of a promise chain
  • will catch any error along the way, stops in chain where error happened
  • place it on the level of the originator, not nested within others
  • can place a .then() after and it will always happen

throw

  • creates a failure within a .then(), .catch() will catch

Promise.all()

  • allows you to wait for all promises to do their thing and return, then you can call .then() for all of them

Promise.resolve() / .reject()

  • create a promise that will succeed or fail.
  • Async / await *
  • function that returns a promise, use async to denote the async function, then await after that function to mimic .then()
async function Something(this) {
  const files = await asyncThing(this);
  const somethingElse = sync(that);
  const anotherThing = await asyncStuff(hmm);
  return anotherThing;
}

Something(this)
  .catch(err => err stuff);

state game v2 demo

  • to listen on a keypress, must have the listener on the entire document
  • have a guard clause to protect against all other keys in listener

Day 13: 3rd party components & mock testing

random notes

building a react app

  • presentation components
    • receive props to create VDOM
    • can callback functions from parents on events
  • container component
    • connect() in redux
    • figures out what state from the store is needed, what functions from action creators
  • parent component
    • organizes placement of children
    • passes data to children
  • action creators
    • functions that create actions from the store
    • handle side effects (impure)
  • selectors
    • can be impure with caching (reselect)
    • typically used in mapStateToProps in connect()
    • are given state and do things to it
  • redux middleware
    • do special things on certain actions
    • not always necessary
  • reducers
    • pure functions that return a new state
    • live in store
  • store
    • where the state and reducers live
  • services
    • expose functions for communicating with external resources
  • advised to start with presentation components. Then create reducers (first) and actions. Then create the store and container component, etc.
  • draw the wireframe with components outline and named
  • create tree of components with data flow of parents to children
  • create routes with mini wireframes

:local(.className) creates a dictionary where the key is the class

  • import styles from './cssFile.css';
  • comes from webpack css-loader

Import hash-router as Router to help with refresh data save.

mock tests (actions with side effects)

  • want to be able to isolate action and test it without worrying about API failures
    • inject api method is tedious and would need a new injection for each test of the action
    • do mocking instead on jest
  • pace mocks before imports, though is not necessary
jest.mock('../../services/api, () => ({
  getAlbums: jest.fn(() => Promise.resolve('PAYLOAD'))
}));
  • Promise.resolve() will succeed with whatever it is given
  • did the result of calling getAlbums assign to payload on the action creator?
  • you can pass in done to jest's it() tests, and call done() when you are done after an async test
  • jest mocks are hoisted to the top of the document

Types of react components

  • 3rd party components, look for stars, when completed, last commit

Pure Components

  • class ThisClass extends PureComponent
  • use with redux / immutable data styles
  • will follow immutable data rules and will not re-render if inputted data is the same as previous data
  • pure function components do not have the lifecycle method shouldUpdate()
  • use destructuring with spread operator when passing into a function to allow for variable props
const TextControl = ({ lable, ...rest }) => {
  <label> {label}:
    <input {...rest}/>
  </label>
}

Styled Components

  • 3rd party component
  • npm i styled-components
  • uses a tagged template literal as a function call
import styled from 'styled-components'

const Button = styled.button`
  color: steelblue;
  background: white;

  ${props => props.primary && css`
    background: palevioletred;
    color: white;
  `}
`;

//can be used as

<Button/>

//can add props in (like a class name!)

<Button primary/>
  • can utilize conditionals / javascript!
  • if you want to switch back to css inside the javascript, use css with backticks
const fancyListItem = styled.li`
  color: ${{ name } => name[0].toLowerCase() === 'j' ? 'blue' : 'green'};
`;
  • allows to drive styling off of data
  • don't mix component styling with styled sheets!
  • can style any component by passing in the className prop

ReactModal

  • component for popup modal
  • tell it whether it is open or not

Day 12: Selectors

random

  • you can use connect to grab props of the parent component. This comes from react-router
(state, props) => ({
  notes: state.notes,
  user: props.match.params.user
})

selectors

  • have their own reducers
  • when creating a filter, have it must be a controlled component
  • create a function (the selector) that converts state data into what you want
  • export the function within the reducers file
  • apply it within the connect statement
  • there is a movement to place selectors for everything within reducers, so that the connect statement is pure and does not modify data itself

reselect

  • memoization of data (re-uses cached values when possible)
  • pass in state to the selector, it is intelligent about what to pull off
  • npm i reselect
createSelector([array of states], (states) => {
  //do something
});

Day 11: Loading, errors, async

random notes

  • Connect
    • takes a component, then returns that component with relevant pieces of state and dispatchers mapped to props wrapped within another component.
    • the dispatch part of the connect function has some shorthand as the boilerplate was repetitive.
export default connect (
  state => ({ notes: state.notes }),
{ makeNote: addNote, fetchNote: loadNotes }
)(connectedComponent);

Error handling

  • app wide vs per feature?
    • do both! specialize when needed.
    • app wide dealing with a loading spinner
      • stays with the header / footer since they are displayed on every page
  • re-type error messages within the async action to be more user-friendly
  • when using fetch
    • there are often responses even if the response was not 'ok'
    • must check with the response is ok to return response.json()

if there is a response without an ok response:

.then(response => {
  response.json().then(body=>{ //smart about where the error resides
    if(body.message) throw body.message;
    if(body.error) throw body.error;
    throw body;
  })
})
  • combine fetching and error handling into own wrapper function in api calls
  • if you find yourself dispatching the same two actions together, combine them
    • such as error clearing with loading of the page
  • better UI to not clear user input on failed form submission!
    • place clearing of the form inside of a promise that only fires if successful
    • throw the error in the action so that it can be picked up elsewhere if needed
  • can get pretty redundant, utilize middleware to wrap a promise in error handling stuff!
const promiseMiddleware = store => next => action => {
  const { type, payload } = action;
  if (!isPromise(payload)) return next(action);

  //handle action here
}
  • if a reducer is expecting a certain format of payload from an action with async, but that action is presenting the payload in a different format for API calls, you can always chain a .then() and present the payload in the desired format
    • useful when the server is returning something that we don't need but we want to change it into something more useful after the promise is fulfilled
export function removeNote(id) {
  return {
    type: NOTE_REMOVE,
    payload: notesApi.remove(id).then(() => id); //implicit return of id for reducer that expects an id instead of what the .remove() is returning
  }
}

Loading

  • sometimes easier create the reducer inside of the test file when starting.
  • initial state of loading should be false, no need for a payload
  • specific actions are not needed since loading is always triggered by async actions
    • will dispatch loading action from fetch action
  • Promises
    • the second parameter of .then() allows for an error handling function, which can catch errors that happen within the .then() promise.
  • console.dir will be more intelligent at displaying what it is attempting to display
  • create a reducer within the loader if there is an error
    • set the loader to false if there is an error
describe('initial state', () => {
  it('initial state', () => {
    const state = error(undefined, {})
    expect(state).toBeNull();
  })

  it('sets an error', () => {
    const state = error(null, {type: ERORR, payload: { message: 'error' } });
    expect(state).toEqual({ message: 'error' });
  });
  
  it('clears an error', () => {
    const state = error({}, { type: ERROR_CLEAR });
    expect(state).toEqualNull();
  });
})

Testing async actions

  • use dependency injection
  • 3 choices
    • mock the dependency (api)
    • change actions so that they accept an api argument that will allow injection of any api, confusing
    • create extra argument in promise middleware (learn tomorrow)

Day 10: White-boarding: Tree traversal

  • iterating through every element in a tree
    • go to the left (not access, go there and make next decision)
    • go to the right (not access, go there and make next decision)
    • visit current element (access value)
    • visit left before right on child nodes

Depth first

  • pre-order
    • as soon as a node is reached, read its value
  • in-order
    • left children, then parent, then right children
  • post-order
    • parent after children

Breadth first

  • visit nodes siblings prior to children
  • Use case: mathematics
    • reverse polish notation (parent is after children)
      • 3 12 7 - *
      • no need to parenthesis

infix operator

function infix(node) {
  let string;
  if(node.left) string+= infix(node.left);
  string+= node.value;
  if(node.right) string+= infix(node.right);
  return string;
}

Tree rotation

  • to help with tree balance when adding and removing nodes.
function pivot(str, node) {
  let direction1, direction2;
  if(str == "left") {
    direction1 = "left";
    direction2 = "right";
  } else {
    direction1 = "right";
    direction2 = "left";
  }
  const newParent = node[direction1];
  node[direction1] = newParent[direction2];
  newParent[direction2] = node;
  return newParent;
}

Day 09: Redux async

Connect

map dispatch to props in long form:

dispatch => {
  return {
    addNote: function(note) {
      const action = addNote(note); //action creator called addNote in actions.js
      dispatch(actionGoesHere); //dispatch the action
    }
  }
}
  • there is the store
    • actions are injected into the store by calling dispatch with the action creators (we call actions by shorthand)
    • store is holding the reducers. Takes the action and updates the state.
    • store sends out a new state, which will trigger re-rending of relevant components

middleware

  • an action is created
  • prior to that action heading off to dispatch, that action can pass through functions (middleware).
  • intercepts dispatch call and modifies data
const logger = function(store) { //longhand
  return function(next) {
    return function(action) {
      if(action.type === 'COMMENT_ADD') {
        action.payload.text += ' haha!';
      }
    }
  }
}

//shorthand
const logger = store => next => action => {
  if(action.type === 'COMMENT_ADD') {
    return action.payload.text += ' haha!';
  }
  return next(action);
}


const store = creteStore(
  reducer,
  composedEnhancers( //for redux dev tools
    applyMiddleware(
      logger
    )
  )
);

  • when dealing with asynch, must only send data to dispatch if the data response was successful
    • cannot create with synchronous actions
  • use thunks!
    • return a function that will call dispatch when they are done with their business
  const asyncanator = store => next => action => {
    if(typeOf action === 'function') {
      action(store.dispatch); //inject dispatch back if the given action is a function
    }
    else {
      return next(action);
    }
  }

  const store = creteStore(
  reducer,
  composedEnhancers( //for redux dev tools
    applyMiddleware(
      thunk
    )
  )
);

Redux Thunk

  • can be used to further simplify actions
    • direction presses reduced into coordinates for a single move instead of reducers for each direction press
  • use with fetch()
    • response.json() will turn the response into a json parsed

Day 08: Redux Store

Store

  • combination of state and reducers
  • store has three methods:
    • dispatch: send an action to the store reducer
    • subscribe(listener): be notified when store state "changes"
    • getState(): get the current store state
  • when a store is not yet created, will send { type: '@@redux/INIT } as first action
  • all actions will flow through all reducers with store.dispatch as there may be multiple reducers for the same action type.
  • createStore(reducers, [initialData], [enhancer]) has an option to see initial data
    • good for development environment
  • make sure to add reducers into store.js!

Connect

  • writes a component that will talk to store
  • will connect a component to the reducers, actions, and data store
  • mergeProps
    • ownProps are passed from a parent to a child
(stateProps, dispatchProps, ownProps) => {
  return { // desired props
    alias: stateProps[specificKey].
    alias: dispatchProps,
    ownProps: ownProps
  }
}

Combine reducer

  • will take in actions and send them to reducers
  • checks if reducers produce a new state
  • if new state is produced, return it, if not, return current state
  • pass in a map of child reducers to combine to pass to the store
  • can bring reducers with aliases CommentsBy: CommentsNotation
  • reducers are always synchronous

const reducer = combineReducers({
  pets,
  people: combineReducers({ //can combine in multiple nestings
    good: goodPeople,
    bad: badPeople
  })
});

Demo

  • create a reducer that will support expensesByCategory
  • create a map that will have a key that is the key of the category
    • an array of the expenses is beneath this key
//start
expensesByCategory = {};

//end
expensesByCategory = {
  categoryId: [
    { 
      name: 'expense name',
      amount: 'expense amount',
      id: 'expense id',
      timestamp: 'expense date'
    }
  ]
}

Day 07: Starting Redux

Random Notes

  • npm i shortid to generate random short ids
  • command + shift + k deletes an entire line in VS code

State

presentation

  • dumb, take props, generally do not have state
  • action creators

actions

  • obtain the events that happen in an app
  • will dispatch state changes
  • call these from component to dispatch desired reducer
  • app logic happens here to change the given object

in actions:

import shortid from 'shortid';
import { NOTE_ADD } from './reducers';

export function addNote(text) {
  node.id = shortid();
  note.timestamp = new Date();

  return { //returns the action
    type: NOTE_ADD,
    payload: note
  }
}

state management

  • lifted away from components
  • more easily accessible my components
  • state will flow back down to re-render a component with updated props
  • in redux, there is one store where all the data lives (single source of truth)
    • except local component state
    • akin to the url being the single source of truth for react router

reducers

  • changes a state based off action
  • typically at least one reducer file per component
  • app logic DOES NOT HAPPEN HERE
  • components should NEVER directly talk to reducers, only actions do that

jest unit reducer test:

import { notes } from './reducers';

it('has a default', () => {
  const state = notes(undefined, {});
  expect(state).toEqual([]);
});

it('NOTE_ADD', () => {
  const noteToAdd = {
    id: 123,
    timestamp: new Date(),
    text: 'New note'
  }

  reducer(notes([], { type: 'NOTE_ADD'. payload: noteToAdd}));

  expect(state).toEqual([noteToAdd]);

  it('removes a note', () => {
    const state = notes([noteToAdd], { type: NOTE_REMOVE, payload: 123})
    expect(state).toEqual([]);
  });

  it('updates a note', () => {
    const updated = {
      id: 123,
      text: 'updated note'
    }

    const state = notes([noteToAdd], { type: NOTE_UPDATE, payload: updated});
    expect(state).toEqual([{ ...noteToAdd, ...updated }]);
  })
}

reducer:

export const NOTE_ADD = 'NOTE_ADD';
export const NOTE_REMOVE = 'NOTE_REMOVE';
export const NOTE_UPDATE = 'NOTE_UPDATE';

export function notes(state, action) {
  switch(action.type) {
    case 'NOTE_ADD':
      return [
        ...state,
        action.payload
      ]
    case 'NOTE_REMOVE':
      return state.filter(n => n.id !== action.payload);
    case 'NOTE_UPDATE':
      const index = state.findIndex(n => n.id === payload.id);
      return [
        ...state.slice(0, index),
        { ...state[index], ...payload },
        ...state.slice(index + 1);
      ];
    default:
      return state;

  }
}

immutable data

  • Component Life-cycle Methods
    • constructor
    • componentWillMount
      • Nobody uses this ¯_(ツ)_/¯
    • componentDidMount
      • Fetching Data
    • componentWillReceiveProps
      • Need to use when updating component that does not re-render
    • shouldComponentUpdate
      • Prevents unnecessary updates
      • skips rendering when no change in data
    • componentWillUpdate* and componentDidUpdate*
    • Nobody really uses these ¯_(ツ)_/¯
    • render +1
  • create a new version of an object with changes instead of mutating
  • makes comparison of previous state and new state much easier (direct comparison)
    • no need to loop through nested items / check every little thing

Working with immutable data:

const person1 = {
  name: 'lady'
}

//add
const person2 = {
  ...person1,
  name: 'good sir' //overwrites any previous stated properties
}

const toys1 = ['cat', 'bat', 'kids'];

//add to array
const toys2 = [
  ...toys1,
  'banana'
];

//delete (usually has id)
const toys3 = toys2.filter(t => t !== 'cat');

//insert

const index = toys3.indexOf('bat');
const toys4 = [
  ...toys3.slice(0,index), //copy up to item of interest
  'mouse', //insert desired item
  ...toys3.slice(index+1) //add everything past item of interest
];

//adding to array of object
const complex1 = {
  name: 'katy',
  toys: ['cat', 'mouse']
}

const complex2 = {
  ...complex1,
  toys: [
    ...complex1.toys,
    'sand'
  ]
};

const complex4 = {
  { name: 'jazz', color: 'red'},
  { name: 'greg', color: 'orange'},
  { name: 'sam', color: 'cans'},
}

const indexOfJazz = complex4.findIndex(p = p.name === 'jazz');
const jazz = complex4[indexOfJazz];
complex5 = {
  ...complex4.slice(0,indexOfJazz),
  {
    ...jazz,
    color: 'grey'
  },
  ...complex4.slice(indexOfJazz + 1);
}

store

  • where the app data exists
  • app is wrapped by a Provider class where the store sits

connect

  • creates the container component for the presentational component
  • links state and actions to the component
    • not necessary to add state if not needed

Design

  • use htmlFor instead of for in inputs and labels
  • have an input field inside of a label and use the htmlFor attribute
  • use <></> to wrap text so as not to create too many divs
  • when mapping and a key is required, use <fragment></fragment>

Day 06: State

random notes

  • webpack 4 was released. When creating a new project, specifically install webpack 3.11.0
  • scrum is a particular subdivision of agile development method.
    • utilize user stories.
    • estimation would assign a value metric to user stories to gauge the effort needed to accomplish that story.
    • add up points from estimation from previous projects to help estimate what can get done in the future

State

  • will mostly be removed from components with redux in a center that controls state

State game

  • rooms:
    • treasure room
    • great hall room
    • starting room
    • bird cage room
  • what does a room have:
    • description
    • doors
      • directional: E, S, W, N
    • items
    • key
      • 'start'
      • 'treasure'
    • use method
      • when an item is used in the room
  • create a room component that works with the room object
  • player:
    • inventory
      • items leave the room and enter inventory

Demo

  • when state is rich with information, create a separate file to store it
  • start with
  • can turn prop-types off in eslintrc.
  • Object.keys will take the key names from an object and push them into an array.
  • when setting state on the content of state, should always use a function as it is handled asynchronously
  • if you want the room to automatically update, you must give it a key so react knows you aren't just changing props

Day 05: White boarding

layers deep in a tree

  • max tree: n-1
  • min tree: (log2(n+1))-1

factorial

  • recursive
function factorial(n) {
  if(n>1) return n*factorial(n-1);
  else return 1;
}

happyNumbers

function happyNumbers(n, prev={}) {
  let digits = n.toString().split('');

  let squares = digits.reduce((total, digit) => total + (digit*digit), 0);

  if(squares === 1) return true;
  if(prev[n]) return false;

  prev[n] = true;

  happyNumbers(squares, prev);
}

Letter permutations

function perm (letters, parent='') {
  if (letters.length === 1) return console.log(parent+letters[0]);

  for(let i=0; i<letters.length; i++) {
    const copy = letters.slice();
    const [letter] = copy.splice(i,1);
    const stem = parent + letter;
    perm(copy, stem);
  }
}

Day 03: React Router and Testing

random notes

  • VSCode when cmd + d, can change casing sensitivity by opening up cmd + f find and change with the casing button.
  • object spread
const person = {name: 'Tammy'}
const obj = {
  color: 'Blue',
  ...person
} // adds person to obj. Will take the right-most and overwrite if properties are the same
  • for omdb reference:
.then(json => json.Response === 'True' ? json : { error: json.Error })
  • in general, create a check notification function

Testing

  • will use jest and enzyme

Jest:

it('passing test', () => {
  const foo = true;
  expect(foo).toBe(true);
});
it('failing test', () => {
  const foo = true;
  expect(foo).toBe(false);
});
  • test or it will do the same thing
  • Test runner will allow code to be written and test it. The prior passed code will be saved as a snapshot in *.test.js.
  • Will throw an error with nice messages, specific to what changed.
  • Double flag (--) in scripts of package.json tells npm to add jests watch
"scripts": {
    
    "test": "jest",
    "test:watch": "npm run test -- --watch",
  },
  • jest will behave differently. Will clear out the consol and add more options
  • update a snapshot npm test -- -u
  • have multiple tests based on if a component exists or not
  • Enzyme will help with testing components (click something, expand something, toJSON)
  • {shallow} rendering from enzyme stops at children (components)

Steps to Creating a snapshot

  • create a static component to render
  • apply styling if need be
  • add functionality to elements (onSubmit, onClick, etc.)
  • add *.test.js of the component
  • add tests for different forms of component
    • simulating functionality
  • run jest to create snapshot
describe('Component' () => {

  it('Renders design', () => {
    const wrapper = shallow(<Component/>);
    expect(toJSON(wrapper)).toMatchSnapshot();
  });
})

  it('Calls onAction with criteria entered', () => {
    let filter;
    const handleAction = _filter => filter = _filter;
    const wrapper = mount(<Component onAction={handleAction}/>); //mount has more actions than shallow

    const action = 'action given';

    // stuff to simulate action

    expect(filter).toBe(action);
  })
  • build propTypes based on props
  • add in props that will be passed into component
  • requires us to think through how a component should be built

Router

  • High level routing usually lives on App.js
  • historyApiFallback: true will serve index.html page if no router match
  • Link tag similar to <a> tag. Will render as tags. Do not place empty tag in react. Will only change what is in the url bar.
  • Router wraps all elements where routes will be served
  • Route wraps components that will be at a particular route. Will only change by what is displayed in url bar.
    • if you place content inside of these tags, they will render if the element is NOT matched
  • exact attribute on route will match exact route only
  • Switch element is like a switch statement, will only match the first one and none of the others
  • Place routes in their own component for easier readability
  • Redirect is a fallback if there are no route matches in Switch
  • render is an attribute on route that will take a function (usually involving match) and render the component with the result as the props
import {BrowserRouter as Router, Route, Link, Switch, Redirect} from 'react-router-dom';
  • can use Route to create special stuff in the header based on the url path!

Day 02: Components and Props

random notes

  • Bulma for pagination in css
  • :local(css-selector) will create a key to give to a react component for scoped CSS styles

Components

  • Think of:
<MyComponent foo={foo} bar="BAR" onQux={this.handleQux}/>
  • As:
const myComponent = new MyComponent({
  foo: foo,
  bar: 'BAR',
  onQux: this.handleQux
});
  • Components are brought in by:
render() {
  <MyComponent/>
}
  • props are brought in by:
render() {
  <MyComponent name={12}/>
}
  • and can be accessed by this.props automatically on the child component MyComponent. Sometimes you pass in props in a constructor in the child component, but only when state needs to be derived from the income props.
constructor(props) {
  this.props = props // not always necessary
}
  • now with class properties (dedicated syntax):
state = {
  count: 1,
  name: grace
};
  • class properties with bound this:
handleUpload = () => {
  this
}
  • this rules:
    • unless explicity set by .call(), .bind(), .apply(), will be the thing to the left of the dot at the call site
    • unless it is an arrow function, then this is wherever the arrow function was defined (lexical scope)
  • .setState() is asynchronous.
  • any time you want to setState() based on the previous state, use functional form of state
this.setState(prev => {
  return { count: prev.count + 1 };
})
  • when state changes, the component is not re-initialized, but is simply rerended based on state change.
    • will re-initialize if you add a key to the component that is tied to state change
    • re-rendering does not always happen with state change
  • conditionals can render in a hide / show manner
  • .setState() accepts a callback to innact after it is done
<span onClick={() => this.setState(prev => ({ expanded: !prev.expanded })))}>{ expanded ? `close` : `open'}</span>
{ expanded ?
  <B name={number}/> //opens the B component
  : null //will show nothing
}
  • alternatively:
{ expanded && <B/>} // if expanded is true, will show B!
{ expanded || <B/>} // if expanded is false, will show B!

State

  • Rules of state
    • Sibling components that share state? Must live in common ancestor
    • Push state a far down as possible
  • Props are state passed from a parent component
  • Child components never modify props directly
  • Never set state outside of constructor
  • Never call setState during synchronous part of render()
  • Use setState(fn) when using previous state

PropTypes

  • dev time feature
import PropTypes from 'PropTypes';

static propTypes = {
  number: PropTypes.number.isRequired
};
  • helps with testing

Search & Pagination

  • all state will exist on APP in this small case
  • break up components
    • search bar
    • pagination
    • results display
    • number of results & search term
  • state
    • total results
    • results per page
    • current page
    • query
    • results
    • page requested
  • assign states to components
    • results display
      • results
      • results per page
    • search bar
      • query
    • pagination
      • page requested
    • number of results & search term
      • query
      • total results
  • information to pass to API from APP
    • query
    • page requested
    • per page
  • information returned from API to APP
    • results
    • page
  • component tree
    • APP
      • results -> list
      • onsearch -> search
      • total results, results per page, onPrev, onNext -> paging

demo

App.js:

state = {
  results: null,
  total: 0,
  query: null,
  page: 1,
  loading: false
}
  • pick between uncontrolled and controlled form types. controlled is linked with state.
  • when you add a state link to a form component, anything you do to that state will render in the form element
    • Ex: .toUppercase() on target in a form input, the input will render with uppercase letters.
    • on submission, would probably want to submit the state then.

Day 01: Tooling (webpack) & React

random notes

  • frameworks / libraries often do the heavy lifting for you so you don't have to interact with the DOM any more.
  • Babel will take ES6 code and transpile it into ES5. Allows use of newer features that browsers do not yet support.

Eslint

  • install eslint-plugin-babel, eslint-plugin-react

Webpack

  • Build step by step and check that it worked.
  • webpack config files are build using node, thus uses older require() format instead of import/export
  • any time config is changed, must restart dev server
  • start and test do not need "run" prior to them in npm start / test
  • Loaders
    • become involved with import/require
  • Plugins
    • do additional work on the resource tree
    • Ex: clean-webpack-plugin, give it a string path of where to clean
  • entry point
    • where webpack will look to seek dependents
  • output
    • where wepack will place the build
    • bundle.[hash].js
      • hash is a cache buster, randomizes the bundle name with each build
    • path must be hard coded in webpack
      • ${__dirname}/build
  • npm adds the direct path location of webpack when you do npm run build
  • webpack-dev-server
    • auto refereshes changes
  • npx will do some magic and find location of path for command given
  • contentBase set to ./build.js
  • html-webpack plugin adds javascript in script tags into html
  • inline-source-map
    • a map between the bundle and what you actually wrote. Makes debuggin in the browser bearable.
    • command + p will bring up desired files
  • need to add a .babelrc file:
    {
      "presets": [
        [
          "env", {
            "targets": { //will be smarter about transpiling
              "browsers": "Chrome 60" //can do 'last two versions'
            }
          }
        ]
      ]  
    }
    
  • babel-core, bable-loader, bable-preset-env
    • placed as a loader in module rules
  • post-css allows nesting
  • css-loader allows css to even work
  • auto-prefixer auto prefixes

React

  • npm i react react-dom eslint-plugin-babel eslint-plugin-react
  • must tell babel to change JSX into React.createElement() in .babelrc
  • import ReactDOM from 'react-dom';
  • import React from 'react';
ReactDOM.render(<div>Hello world</div>,
document.getElementById('root'))
  • pretend components are an element <App /> and react will call that component
  • even though the entire render() method is called during a setState(), only the changes are rendered in the DOM.
import React, { Component } from 'react';

export default class App extends Component {

  constructor() {
    super(); //do not forget to call!
    this.state = {
      name: 'Portland'
    };

  handleNameChange({target}) {
    this.setState({
      name: target.value
    });
  }

  }
  render() {
    const { name } = this.state;
    return ( //not necessary but to help for readability
    <div>
      <div><input value={name} onChange={ event => this.handleNameChange(event)}/></div> //eventListeners are camelCase
      <div> 
        Hello {Name}! //interpolation via single curly braces. don't need extra white space like objects
      </div>
    </div>
    );
  }
}
  • State -> render() -> virtual DOM -> compares to last virtual DOM -> DOM changes -> events -> actions -> changes to state -> back to State
  • There are multiple ways to resolve the this problem within react.
    • when event listeners are created within the render method, it will be recreated each re-render, which isn't so bad but is annoying to the community
    • binding this to each method on the class in the constructor
  • &nbsp; in JSX creates a non breaking whitespace
  • when styling inline in JSX:
<input style={{
  backgroundImage: background ? `url(${background})` : null
  ref={node => this.section = node} //to remember the node referred to
}}/>
<input type="file" onChange={handleUpload}/>
  • base64 loading of file upload
handleUpload({target}) {
  const reader = new FileReader();

  reader.readAsDataURL(target.files[0]);
  reader.onload = () => {
    this.setState({ background: reader.result})
  }
}

lab

  • Faker API creates lots of random yet usable content
  • wrap option in cowsay?
  • npm i dom-to-image file-saver for exporting memes as images
  • cors error in taking a url from protected websites
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment