接觸react-hook已經(jīng)很久了缝彬,用了之后,發(fā)現(xiàn)真的很強大哺眯,記錄一下最近使用的想法
useState
首先接觸到的就是useState
state只是一個狀態(tài)谷浅,但是之前class就需要寫的很大,相比之下族购,寫成hook就簡化了很多
class Age extends React.Component {
constructor(props) {
super(props);
this.state = {
age: 20
};
}
handleOnChange = e => {
const { name, value } = e.target;
this.setState({ [name]: value });
};
render() {
return (
<>
<div>age: {this.state.age}</div>
<input name="age" onChange={handleOnChange} />
</>
);
}
}
用了hook之后壳贪,就變得很簡潔了
const Age = () => {
const [age, setAge] = React.useState(20);
const handleOnChange = e => {
const { value } = e.target;
setAge(value);
};
return (
<>
<div>age: {age}</div>
<input name="age" onChange={handleOnChange} />
</>
);
};
useEffect
對于useEffect我最初以為是用來替代生命周期,比如componentDidMount
寝杖,但是事實證明他真的很強大违施,[name]
括號里面的是依賴,依賴一變瑟幕,就會重新執(zhí)行磕蒲,多個依賴就更棒了,如果是用之前的寫法只盹,就要在 componentWillReceiveProps
里面寫很多if來比較nextProps
和this.props
而且這個最強大就是可以抽出來辣往,當一個反復利用reuseable的hook
傳入不同的localStorageKey
,就可以存不同的數(shù)據(jù)到localStorage
殖卑, 這樣就方便重復實用了站削,而且每次value
變了,就會自動保存到localStorage
const useLocalStorage = localStorageKey => {
const [value, setValue] = React.useState(
localStorage && localStorage.getItem(localStorageKey)
);
React.useEffect(() => {
localStorage && localStorage.setItem(localStorageKey, value);
}, [value, localStorageKey]);
return [value, setValue];
};
useRef
有些時候孵稽,會發(fā)現(xiàn)许起,其實數(shù)據(jù)并沒有變化,但是還是觸發(fā)了setState或者是別的callback菩鲜,這樣會導致园细,調(diào)用的函數(shù)太多,從而影響了性能接校,所以比較兩個對象是不是相等猛频,只有當不等,才更新蛛勉,這樣可以減小一點re-render鹿寻。
這時候,就是useRef登場的時候了董习,搭配實用lodash.isEqual, 可以比較大的object
const usePrevious = value => {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
};
#使用
const myPreviousState = usePrevious(conditions);
useEffect(() => {
if (myPreviousState && !_.isEqual(myPreviousState, conditions)) {
onChange(conditions);
}
}, [myPreviousState, conditions, onChange ])
useContext
context呢烈和,我之前一直覺得這個東西很高大上,很復雜皿淋,一直不敢用招刹,但是后來發(fā)現(xiàn)恬试,他就是對應上下文,比如傳遞props疯暑,一般都是使用parent傳給child训柴,但是如果,A -> B -> C -> D妇拯,但其實B和C都沒用到幻馁,只有D用到了,那么D要來修改A越锈,就需要再往上傳遞仗嗦,導致B和C一直在反反復復被重新渲染,這時候甘凭,當當當當稀拐,context就可以發(fā)揮很大的作用,在A里面包一下Provider丹弱,然后到D直接用createContext
和useContext
拿出來就可以用了德撬,這樣代碼也不會忘了忘記中間的B,C的pass props躲胳,看起來也清楚蜓洪,何樂而不為呢
const NameContext = createContext();
const A = () => (
<NameContext.Provider value={{ username, setUserName }}>
<B />
</NameContext.Provider>
);
const Names = () => {
const { username, setUserName } = useContext(NameContext);
const { names, onChange } = useNames({ username, setUserName });
return (
<div>
<label>firstName</label>
<input
name="firstName"
value={names && names.firstName}
onChange={onChange}
/>
<label>lastName</label>
<input
name="lastName"
value={names && names.lastName}
onChange={onChange}
/>
</div>
);
};
useReducer
最后是用到redux, 之前對于redux的理解一直如果當一個對象,要被很多不同的地方共享和修改坯苹,那么放到redux是最合適不過隆檀。但是知道我遇到了,一個嵌套很深的一個object粹湃,要更新里面的某一個字段真的要寫好多好多層刚操,然后我翻到了hook對于useReducer的介紹
Another option is useReducer, which is more suited for managing state objects that contain multiple sub-values.
useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one. useReducer also lets you optimize performance for components that trigger deep updates because you can pass dispatch down instead of callbacks
現(xiàn)在的reducer是相對于useState而言的,他更加適合復雜的再芋,有很多sub-values的對象的更新
import React, { useEffect, useContext, createContext, useReducer } from "react";
const NameContext = createContext();
const init = initial => {
return { name: initial };
};
const reducer = (state, action) => {
switch (action.type) {
case "firstName":
return {
...state,
name: {
firstName: action.payload
}
};
case "lastName":
return {
...state,
name: {
lastName: action.payload
}
};
default:
return state;
}
};
const useNames = ({ username, setUserName }) => {
// const [names, setNames] = React.useState(username);
const [state, dispatch] = useReducer(reducer, username, init);
const names = state.name;
const onChange = e => {
const { name, value } = e.target;
dispatch({ type: name, payload: value });
};
useEffect(() => {
setUserName(names);
}, [names, setUserName]);
return {
names,
onChange
};
};
const Names = () => {
const { username, setUserName } = useContext(NameContext);
const { names, onChange } = useNames({ username, setUserName });
return (
<div>
<label>firstName</label>
<input
name="firstName"
value={names && names.firstName}
onChange={onChange}
/>
<label>lastName</label>
<input
name="lastName"
value={names && names.lastName}
onChange={onChange}
/>
</div>
);
};
const App = () => {
const [username, setUserName] = React.useState({
firstName: "Rachel",
lastName: "Green"
});
return (
<NameContext.Provider value={{ username, setUserName }}>
<Names />
</NameContext.Provider>
);
};
export default App;
完成了一個簡簡單單的name 表單組