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
Post a Comment