This post was originally posted on my blog
Last time, I got more than 500 likes on Zhihu after I finished the four front-end handwriting, which really made me feel flattered. On the one hand, I want to review React Hooks, on the other hand, I want to share with you some of my own experiences learning React Hooks. Because of my limitations, I will share some basic tips on how to use React Hooks. I will update you on the principles of Hooks in the future.
Let’s take a look at the byte interview question, the topic is to implement a custom Hook, click to switch state.
function SomeComponent() {
const [state, toggleState] = useToggle(false);
return <div>
{state ? 'true' : 'false'}
<button onClick={toggleState}></button>
</div>
}
// Implement useToggle
function useToggle(initialValue) {
const [value, setValue] = useState(initialValue);
const toggle = () = >{setValue(! value)};return [value, toggle];
}
Copy the code
Which are the seven Hooks
useState
stateuseEffect
The hook, and its brotheruseLayoutEffect
useContext
contextuseReducer
Instead of a storyuseMemo
The cache, and its little brotheruseCallback
useRef
referenceCustomize the Hook
hybrid
useState
Const [X, setX] = react.usestate (initial value of X)
A simple example:
function App() {
const [user,setUser] = useState({name:'Varian'.age: 18})
const onClick = () = >{
setUser({
name: 'Janye'})}return (
<div className="App">
<h1>{user.name}</h1>
<h2>{user.age}</h2>
<button onClick={onClick}>Click</button>
</div>
);
}
Copy the code
We can see that when we click the button, age disappears, but we just changed the name. Why?
In simple terms, it’s two completely unrelated objects.
React creates a new virtual DOM object when the data changes, and then performs a DOM Diff with the original virtual DOM to create a minimal change Patch. Render the Patch on the page. Diff found that the new object did not have the age property, so I removed it.
There are two things to be aware of when using useState:
- To get the original value, you have to copy it in setX, something like that
setUser({... user, name: 'Janye'})
- When setX(obj), the address of obj must change
useEffect
UseEffect is primarily used to solve the problem of how function components use lifecycle hooks as class components do.
It has three usage scenarios:
- Used as componentDidMount, the second argument is an empty array
[]
- Used as componentDidUpdate, the second argument specifies the dependency
- Used as componentWillUnmount, via return
Here’s the simplest example:
const BlinkyRender = () = > {
const [value, setValue] = useState(0);
useEffect(() = > {
document.querySelector('#x').innerText = `value: 1000`
}, [value]);
return (
<div id="x" onClick={()= > setValue(0)}>value: {value}</div>
);
};
ReactDOM.render(
<BlinkyRender />.document.querySelector("#root"));Copy the code
So how is it different from its cousin, useLayoutEffect? UseEffect is executed after the browser renders, useLayoutEffect is executed before the browser renders, useLayoutEffect is always executed before useEffect.
So for the user experience (see first render first), we should usually useEffect first.
useContext
If we want to share state between components, we can use useContext.
Its use can be divided into three steps:
- use
C = createContext(initial)
Create context - use
<C.provider>
Define the scope - Used within scope
useContext(C)
To use context
A simple example:
const C = createContext(null);
function App() {
console.log("App executes.");
const [n, setN] = useState(0);
return (
<C.Provider value={{ n.setN}} >
<div className="App">
<Baba />
</div>
</C.Provider>
);
}
function Baba() {
const { n, setN } = useContext(C);
return (
<div>I am the father n: {n}<Child />
</div>
);
}
function Child() {
const { n, setN } = useContext(C);
const onClick = () = > {
setN(i= > i + 1);
};
return (
<div>I'm the son and I get n: {n}<button onClick={onClick}>+ 1</button>
</div>
);
}
Copy the code
useReducer
UseReducer is a replacement for Redux, or an enhanced version of useState, if you have to explain it in one sentence.
In terms of usage, there are four steps:
- Create the initial value initialState
- Create all operations Reducer (state, action)
- Pass it to useReducer to get the read and write API
- call
Write ({type: 'operation type '})
Here’s a basic example:
const initial = {
n: 0
};
const reducer = (state, action) = > {
if (action.type === "add") {
return { n: state.n + action.number };
} else if (action.type === "multi") {
return { n: state.n * 2 };
} else {
throw new Error("unknown type"); }};function App() {
const [state, dispatch] = useReducer(reducer, initial);
const { n } = state;
const onClick = () = > {
dispatch({ type: "add".number: 1 });
};
const onClick2 = () = > {
dispatch({ type: "add".number: 2 });
};
return (
<div className="App">
<h1>n: {n}</h1>
<button onClick={onClick}>+ 1</button>
<button onClick={onClick2}>+ 2</button>
</div>
);
}
Copy the code
useMemo
Basic syntax: useMemo(callback function, [dependency])
Similar to Vue’s computed property, computed, useMemo has the ability to cache and re-render depending on changes.
The only difference between useCallback and useMemo is that useMemo can cache all objects, whereas useCallback can only cache functions.
UseCallback (x = > log (x), [m]) is equivalent to useMemo (() = = > > x log (x), [m])
useRef
The main function is to create a reference to the data and keep it constant throughout the render process.
Const count = useRef(0)
Here’s an example of how I encapsulated Echarts:
export function ReactEcharts(props) {
const {option, loading} = props
const container = useRef(null)
const chart = useRef(null)
useEffect(() = > {
const width = document.documentElement.clientWidth
const c = container.current
console.log(c)
c.style.width = `${width - 20}px`
c.style.height = `${(width - 20) * 1.2}px`
chart.current = echarts.init(c, 'dark')}, [])// [] - mounted on first time
useEffect(() = > {
chart.current.setOption(option)
}, [option]) // When option change is similar to vue watch
useEffect(() = > {
if (loading) chart.current.showLoading()
else chart.current.hideLoading()
}, [loading])
return (
<div ref={container}/>)}Copy the code
Customize the Hook
We can mix the above hooks according to actual requirements and encapsulate them into a function, giving a simple example:
const useList = () = > {
const [list, setList] = useState(null);
useEffect(() = > {
ajax("/list").then(list= >{ setList(list); }); } []);// [] Make sure to run only the first time
return {
list: list,
setList: setList
};
};
export default useList;
Copy the code
Write in the last
Based on my recent interview experience, I have two thoughts to share with you:
- The learning and improvement of technology cannot be separated from persistent practice. It is necessary to constantly review the old and learn new things to overcome the forgetting curve.
- Make good use of every opportunity to communicate with the interviewer, for their unfamiliar knowledge points for timely reflection and review, to further improve their knowledge system.