自定义hooks
作为react的使用者,自定义hooks是常见的业务需求,小弟技术水平有限,只能先借花献佛聊下公司里大佬们封装的自定义hooks了
import { useRef } from 'react';
export type ShouldUpdateFunc<T> = (prev: T | undefined, next: T) => boolean;
const defaultShouldUpdate = <T>(a?: T, b?: T) => a !== b;
export function usePrevious<T>(
state: T,
shouldUpdate: ShouldUpdateFunc<T> = defaultShouldUpdate,
): T | undefined {
const prevRef = useRef<T>();
const curRef = useRef<T>();
if (shouldUpdate(curRef.current, state)) {
prevRef.current = curRef.current;
curRef.current = state;
}
return prevRef.current;
}
保存上一次状态的 Hook。
用法如下
记录上一次的count值
import { usePrevious } from '@pansy/react-hooks';
import { Button } from 'antd';
import React, { useState } from 'react';
export default () => {
const [count, setCount] = useState(0);
const previous = usePrevious(count);
return (
<>
<div>counter current value: {count}</div>
<div style={{ marginBottom: 8 }}>counter previous value: {previous}</div>
<Button onClick={() => setCount((c) => c + 1)}>
increase
</Button>
<Button style={{ marginLeft: 8 }} onClick={() => setCount((c) => c - 1)}>
decrease
</Button>
</>
);
};
只有 shouldUpdate function 返回 true 时,才会记录值的变化。
import React, { useState } from 'react';
import { Button, Input } from 'antd';
import { usePrevious } from '@pansy/react-hooks';
interface Person {
name: string;
job: string;
}
const nameCompareFunction = (prev: Person | undefined, next: Person) => {
if (!prev) {
return true;
}
if (prev.name !== next.name) {
return true;
}
return false;
};
const jobCompareFunction = (prev: Person | undefined, next: Person) => {
if (!prev) {
return true;
}
if (prev.job !== next.job) {
return true;
}
return false;
};
export default () => {
const [state, setState] = useState({ name: 'Jack', job: 'student' });
const [nameInput, setNameInput] = useState('');
const [jobInput, setJobInput] = useState('');
const previousName = usePrevious(state, nameCompareFunction);
const previousJob = usePrevious(state, jobCompareFunction);
return (
<>
<div style={{ margin: '8px 0', border: '1px solid #e8e8e8', padding: 8 }}>
<div>current name: {state.name}</div>
<div>current job: {state.job}</div>
</div>
<div>previous name: {(previousName || {}).name}</div>
<div style={{ marginBottom: 8 }}>previous job: {(previousJob || {}).job}</div>
<div style={{ marginTop: 8 }}>
<Input
style={{ width: 220 }}
value={nameInput}
onChange={(e) => setNameInput(e.target.value)}
placeholder="new name"
/>
<Button
onClick={() => {
setState((s) => ({ ...s, name: nameInput }));
}}
style={{ marginLeft: 8 }}
>
update
</Button>
</div>
<div style={{ marginTop: 8 }}>
<Input
style={{ width: 220 }}
value={jobInput}
onChange={(e) => setJobInput(e.target.value)}
placeholder="new job"
/>
<Button
onClick={() => {
setState((s) => ({ ...s, job: jobInput }));
}}
style={{ marginLeft: 8 }}
>
update
</Button>
</div>
</>
);
};
个人的分享记录,不喜勿喷。