Stephen Grider – Modern React with Redux




Section 1

install node js
npm install -g create-react-app
npm create-react-app app_name

Semantic UI, https://semantic-ui.com/, insert cdn script to index.html root.
Section 2,3 – Basics


import React from ‘react’;
import ReactDOM from ‘react-dom’;


const App = () => { return (div) } //functional component

ReactDOM.render(<App />, document.getElementById(‘root’));


Receiving/passing props


const ExpenseCard = props => { return(<div>) }
<ExpenseCard abc=”” />, access by props.abc
<ExpenseCard> sth else/component etc </ExpenseCard>, access by props.children
Section 4,5,6 – Class-based component, States, Life Cycle Methods

Class component & props
as a Class extends on sth, call super() for inheritance


class AssetCard extends React.Component {
constructor(props) {
super(props);
}

//life cycle methods here
//other functions here

render() {
// can do some calculation before return
return (div)
}



State


this.state = {} // Initialization inside constructor()
state = {} // Initialization outside constructor()
this.setState{} // modify states

Why state instead of props? To re-render a component every time state is update (due to delay in async calls, etc.)
Section 7 – Form & Events

Events: onChange, onClick, onSubmit

Controlled vs Uncontrolled elements

this , binding this to certain class scope, using 1. bind in constructor(), or 2. => function

Communicating from Child to Parent, with state, callbacks


Section 8 – API request

Axios, npm install –save axios
import axios from ‘axios’

axios.get(‘url’,{options/ headers:{} params:{}})


Section 9 – Render lists with Map

list.map(ele => do anything to ele, returns an array)


Section 10 – DOM access

Vanilla JS: document.getElement(‘img’).clientHeight, for example



React Refs

in constructor(),


this.anyRef = React.createRef()

add Ref to JSX attribute/tag


<img ref={this.anyRef} etc. />

to access Ref’s attributes, sometime the element needs to completely load => add callbacks/ .addEventListener(‘load’, funciton) once loaded with


Section 12 – Redux

npm i redux







Action Creator – a function, that will create a JS object – Action, that has type and payload property. Type = the change to make, Payload = context of the change.

Dispatch – a function, that makes copies of the Action object and sends to Reducers, functions that take in Actions & some data, process them, return to centralize in State.

Typical Action Creator functions:



Typical reducer, always return a copy of array by […oldArray, newElement], do not modify old array by oldArray.push(newElement). First time running, the oldArray is blank/undefined, so let’s default it to [] empty array.











Redux library


const {createStore, combineReducers} = Redux

const reducers = combineReducers({
stateName: reducer,
stateName: reducer })

const store = createStore(reducers)

const action = createPolicy(anyname,anyamount)
store.dispatch(action) // dispatch the action to store/reducers
store.getState() //return the state






Section 13 – React Redux

npm i redux react-redux

The store here is where we have all our states/data stored.

Provider is actually rendered at a very top of the component hierarchy, even above App.

Connect communicate up to Provider using the Context system, not props, it allows direct communication between parent and sub-sub children level without passing data though the mid-level components. Connect helps to get state and save data to state.



Default vs Named exports


If the end of file, export default abc => import abc from ‘file’

If right at abc, export const abc = … => import { abc } from ‘file’



combineReducers file structure:


import {combineReducers} from ‘redux’

reducers functions here~~~

export default combineReducers({
state:reducer function,
song: songReducer
})



Add Provider & Store to <App />


import { Provider } from ‘react-redux’;
import { createStore } from ‘redux’
import reducers from ‘./reducers’

ReactDOM.render(
<Provider store={createStore(reducers)}> <App />
</Provider>,
document.getElementById(‘root’));



Add Connect into child components


import {connect} from ‘react-redux’
import {functions} from ‘./actions/’

class/function component

const mapStateToProps = ( ) => { //same as function mapSTS() {}
return { songs: state.songs} // this whole object then can be accessed with this.props
}

export default connect(mapStateToProps, {functions} )(Component)
// to pass in functions (actions), which can be accessed with this.props.function, what returned is sent to reducers


Section 14 – Redux Thunk

npm i redux-thunk

Cant make a request inside an Action creator like this, because async make it a promise, not pure object as required by redux.



redux-thunk is a kind of middleware (called for every actions in redux) that modifies redux rules a bit by allowing returning functions (not only object), and hence helps to make network request.

Seperate route for dealing with functions, thunk now has access to



Wire redux-thunk into redux store, typo beware, applyMiddleware not applyMiddleWare


import { applyMiddleware } from ‘redux’

import thunk from ‘redux-thunk’

const store = createStore( reducers, applyMiddleware(thunk) )

<Provider store={store}>




Refactor action with thunk, to return a function, i.e to work with async await. Using dispatch instead of return the action object.



some more refactoring:




Section 15 – Redux Store







First time boot up, react will run all reducers once, hence arguments should have default value to null to not return undefined

Be careful when dealing with state input object:

We can add calculations and logic to alter the state in the mapStateToProps function! It also have access to props with the 2nd argument ownProps.

const mapStateToProps = (state, ownProps ) => {}

_.memoized(function) to remember and call a function with a certain set of args only once. CAREFUL when memoize nested functions ~~

Action creator can be nested, hmm, where an action creator can call another action creator, in this case, we’ll need to call by dispatch(the other action).

getState() to access the current State object in redux




Section 16 – React Router

Docs: https://reacttraining.com/react-router/core/guides/quick-start



npm i react-router-dom





react-router only sees the part after the slash /

Without ‘exact’ (equivalent to exact = {true}) it shows all paths contained in the extracted path, for example, /page will show both “/” and “/page”



DO NOT use <a href=”url”> tag for path, because this will trigger a new request, reload the page and forget/dump all redux,state variables etc.

USE <Link to=”url”> instead

When request to non-existing url, router will return index.html. (by default, even when requesting the correct url, it’ll load the index.html (after dev resources & static)-> check bundle.js -> check current url -> render correct page)



Reason to use Hash, we can config the server to ignore url after/with the Hash #.

So when deploy react-router and get 404, check your server/backend set up.



Always visible component, either 1. add the component outside the Router, or 2. simply use the component without Route (when using Link, or other Router component, or else it’ll show error)..










Section 17 – OAuth

OAuth, login with Google or Facebook API, then can make actions on behalf of the users.



Scopes – what can be accessed, keywords “google oauth scope list”

console.developers.google.com, get an account and
1. Create a new project,
2. Create an Oauth consent screen
3. In Credential, create an Oauth client ID, save the clientID
4. Insert this script html file: https://apis.google.com/js/api.js

After this, gapi function can be called from console tab. Learn more about related methods by keywords “gapi documentation”.
https://github.com/google/google-api-javascript-client/blob/master/docs/reference.md



auth = window.gapi.auth2.getAuthInstance()
auth.signIn()
auth.signOut()
auth.isSignedIn.get()
auth.isSignedIn.listen(f) to await for changes in signedIn status, callback to run function f

auth.currentUser



Tips: define redux const = string in types.js, import to use to avoid silent typo mistakes.

The one below is just for activating the gapi library






Section 18 – Debug redux store

Add chrome Redux Devtools extension



https://github.com/zalmoxisus/redux-devtools-extension

Wire in App component:


import { compose } from ‘redux’

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(reducers, composeEnhancers(applyMiddleware(thunk)))

To save redux state between refreshes, use link:


localhost:3000?debug_session=<abc string>




Section 19 – Redux form

Documentation redux-form.com

npm i redux-form

Automate, abstract all redux “repetitive” logic, i.e reducer, actionCreator. We only need to care about getting the props and handler.





Set up in Reducer



Component wiring, reduxForm functionality is very similar to Connect of Redux


import {Field, reduxForm} from ‘redux-form’

class ABCComponent

export default reduxForm({
form: ‘whateverName’
}) (ABCComponent)

Field, a wrapper around an input component, with a name, and necessary callback functions


<Field name=’whatever’ component={this.anyComponent}/>

In anyComponent render function, need to pass necessary props to Input, so that Form can work properly. anyProps usually includes onChange and Value functions etc. Extra props to Field will be passed to anyComponent as props


anyComponent(formProps) { // can be shortened to {input, label, extraProps from Field}
return (<>
<label> {formProps.label) </label>
<input {formProps.input} />
</>)}

<Field name… component… label=’xxx’/>



submit by handleSubmit of redux-form


onSubmitFunction(formValues){ //receive all

}

<form onSubmit={this.props.handleSubmit(this.onSubmitFunction~~~)}>
<Field> …
<Button>
</form>

Validation, define a seperate function, which has all formValues passed in.
Then check each value, return empty object {} if ok, error msg if not, for example {fieldName: ‘oops please enter correctly~~’} . The error values will be passed to formProps.meta.error

Finally pass the validate function to reduxForm export.

Better to only show errors, when meta.touched is true, i.e user has interacted with the input.



Code sample










Section 20 – RESTful

REST convention GET POST PUT DELETE

npmjs.com/package/json-server, npm init, npm install –save json-server, create blank db.json, insert script to package.json “start” : “json-server -p 3001 -w db.json”, npm start.

actions.js will contain actual commands to the server, i.e post will create new entry in db.json ( axios.post(“/streams”) will add to streams key).

array based state is hard to maintain/update. Object based with keys is easier to maintain, as each can be accessed quickly and neatly with a key. Special treatment with mapKeys & omit.



redux actions can have 2 arguments, dispatch & getState, getState is used to access info from state.



User Navigation vs Programmatic Navigation, need access to history object, but history object is hard to pass around, another approach is to create history object to use with Router, not BrowserRouter.

Show component with any variable after a path
Route path=”/streams/edit/:variable” component={component} />

mapStateToProps can take 2 arguments: state, redux state object and ownProps, props of the current component.

React-Router needs each component to work in isolation (fetch its own data)

When user refreshes a page, state is cleared without any values -> cannot render page with correct/any info -> re-fetch state data in componentDidMount for every component.

initialValues link to Field names to pass default values to Form

PUT request with replace the whole object, PATCH request will update only new values.
Section 21 – Portals

modal render on top, using css z-score for div, the higher the more on top.

portals help to render component not as a direct child, first add a div tag with id, then RenderDOM.createPortal to that div. Then that <Modal /> can be inserted to any component without being rendered as a child. Best to make the modal generic and can be reused in various ways.





If nested html has no handler for click event, it will trigger the click event handler of the parent html tags.

<React.Fragment> </React.Fragment> or <> </>, invisible wrapping instead of <div>, helps in certain cases where <div> needs to be eliminated.
Section 22 – Streaming

import Switch and wrap around Router , to show only 1 route at a time.

again, as before, the stream needs time to fetch so we need to handle when it’s not ready yet



RTMP Server: https://github.com/illuspas/Node-Media-Server
OBS: https://obsproject.com/
flv.js: https://www.npmjs.com/package/flv.js
Section 23 – Context

Context is used to pass Props from a parent component to a deeply nested child, without passing through any intermediate component.

1. Create context


2. Get data from context, 2 approach, static contextType or Consumer. Consumer need to wrap around a Function!




3. Change context, import created contexts and wrap their Provider components around the component that needs data.

Section 24 – Context replacing Redux

Simply have an object in context, instead of simple string values, and link appropriately from other components to that object context
Section 25 – Hooks

To add state (useState), life cycle methods (useEffect) to Functional Components



Example implementation:



useEffect cant be called with a promised function, so must define an extra function and invoke it in useEffect.

prevProps, refers to previous Props, can be passed in as an argument to.

Comments

Popular posts from this blog

Bryan Peterson – Learning to See Creatively

R – Stats, factor count,proportion

R - Supervised Learning