React overview
Init react
Commend
|
|
npx means you use this package but don’t download it.
or with redux
|
|
life cycle
![](https://tyrangyang.github.io/TyrangYang_blog/images/2019-10-03-react/rcc.png)
Class component lifecycle
![](https://tyrangyang.github.io/TyrangYang_blog/images/2019-10-03-react/rfc.jpg)
Function component method
shouldComponentUpdate()
Run before render()
to check this component need to render or not.
|
|
PureComponent
can automatically do a shallow comparison to determine need to update or not
export default React.memo(<component name>)
only compare props but it works for functional component
getSnapshotBeforeUpdate
it is invoked right before the most recently rendered output is committed
|
|
getSnapshotBeforeUpdate
must pair with componentDidUpdate()
Context API
Doc: https://reactjs.org/docs/context.html#reactcreatecontext
Use a context:
- React.createContext({defaultValue})
- import the context your create. Warp you root component which you want to use this context in <ContextName.provider ></ContextName.provider>
- component under root context component will access to this context
- static contextType = MyContext
- Warp component like
|
|
All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes. The propagation from Provider to its descendant consumers (including .contextType and useContext) is not subject to the
shouldComponentUpdate
method, so the consumer is updated even when an ancestor component skips an update.
Context API is not for solve all state sharing problem. Think like Context provider change(even prevent update by shouldComponentUpdate
) all consumer will re-render.
The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Note: passing undefined as a Provider value does not cause consuming components to use defaultValue.
Ref
React.createRef()
API introduced in React 16.3. If you are using an earlier release of React, we recommend using callback refs instead.
There are a few good use cases for refs:
- Managing focus, text selection, or media playback.
- Triggering imperative animations.
- Integrating with third-party DOM libraries.
create ref
|
|
access ref
|
|
Adding a Ref to a Class Component
|
|
Adding a Ref to a Functional Component
By default, you may not use the ref attribute on function components because they don’t have instances:
If you want to allow people to take a ref to your function component, you can use forwardRef
(possibly in conjunction with useImperativeHandle
), or you can convert the component to a class.
useImperativeHandle + ForwardRef
|
|
In this example, a parent component that renders <FancyInput ref={inputRef} />
would be able to call inputRef.current.focus()
.
React Hooks
useState
|
|
useEffect
|
|
useContext
Given an Example for useContext + useReducer
In ContextProvider.jsx
|
|
In ContextConsumer.jsx
:
|
|
useContext(MyContext)
is equivalent to static contextType = MyContext
in a class, or to <MyContext.Consumer>
But You still need a <MyContext.Provider>
above in the tree to provide the value for this context.
useReducer
|
|
Unlike Redux
dispatch
function doesn’t need to add inuseEffect
oruseCallback
dependence list sincedispatch
always be a same function
setState by useReducer
Usually we set a state by useState. But if the state is simple boolean,useReducer
is the shortest way to create a state for toggle a boolean value
|
|
relation with useState,
Theoretically, useReducer is a more general useState hook.
|
|
That is whydispatch
always be same. (setState always same in useState)
useRef
useRef()
creates a plain JavaScript object. The only difference betweenuseRef()
and creating a{current: ...}
object yourself is that useRef will give you the same ref object on every render.
useLayoutEffect
The only different between useLayoutEffect
and useEffect
is that the useLayoutEffect
is synchronous. Just same as componentDidMount
and componentDidUpdate
.
- useLayoutEffect()
- render
- useEffect()
useImperativeHandle
useImperativeHandle
customizes the instance value that is exposed to parent components when using ref. It is rare to use.
This is use for handle using ref to access functional component.
React.lazy()
The
React.lazy
function lets you render a dynamic import as a regular component.
Component only be loaded when it will be rendered
|
|
You can even wrap multiple lazy components with a single
Suspense
component.
Class Component vs Functional Component
Class Component lifecycle ==> Functional Component hooks
Class component | Functional component |
---|---|
state + setState | useState() |
componentDidMount() | useEffect() with a empty input list |
componentDidUpdate() | useEffect() with a input list contained which you want to change |
componentWillUnmount() | useEffect() with a return callback function |
shouldComponentUpdate() | export default React.memo( |
Logic extraction
Suppose we have two components A
and B
that B
is depends on A
, the common solution is wrapping B
in A
. However,
when the logic in A
need to reuse, we cannot copy and parse A
to everywhere. Extracting the logic is essential.
|
|
This Blog is an example to extract logic by Three different way: Check this Blog
High-Order Component
Concretely, a higher-order component is a function that takes a component and returns a new component.
|
|
Render props
Concretely, a render prop is a function prop that a component uses to know what to render.
|
|
Customize Hooks
Concretely, A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks.
|
|
Common Pitfall
Performance difference (SnapShot vs Current value)
When React introduce hooks for functional component, closure problem will be brought in as well. This will cause different performance between class component and function component with same logic.
These two component have same logic:
|
|
Play with this example: Link
Click Get
button first and then click double
. Class component will alert current value, however function component will alert snapshot.
This is not a bug. This is a common question in Javascript due to the fact that every time you passing same reference or not.
See another example: closure loop problem
In React, Because props
is immutable(assign a new obj when you want to change it) in functional component, each rendering has different props
. Every click will generate a new props and setTimeout()
display the value when you click. However, in Class component. After class generated, props
is associated with class itself. Every rendering in class component have same this.props
and this.props.user
change overtime. Therefore, setTimeout()
use same this.props
and access this.props.user
which is current value.
This flowing code simulate this problem
|
|
Solution
Since we know different props display snapshot and same reference display current value.
To get snapshot in class component, just assign the data that will alert to a new variable. (give several different value)
To get current value in functional component, add a ref(react) / create a value outside the component and store value to it. (give a same reference)
Initial state from props
Ref: https://react.dev/learn/choosing-the-state-structure#don-t-mirror-props-in-state
It is NOT RECOMMEND that initialized state from props directly. Update props won’t be reflected in the state. Because initialize state only run once
Only use this pattern if you intentionally want to ignore prop updates.
Class Base:
|
|
Functional Base:
|
|
|
|
If really want to convert props to status. It should use be:
Class Base:
|
|
Functional Base:
|
|
Trick
inject props to children
For example, we have a Wrapper component:
|
|
if we want to inject a props to children. Could use cloneElement()
to achieve.
|
|
Reference from React.dev
React Posts Archive
Structure
package.json
react & react-dom is necessary for web app. For mobile app need react-native instead of react-dom.
public/index.html
signal page application which is index.html
Everything your do will inside <div id="root"></div>
src/index.js
Entry point for react
src/App.js
All the component.
Inside the class, the render() method is called life cycle method and to render the page.
In JSX, you cannot use HTML class attribute. you have to use className.