React Hooks上手
1、自定义hooks
- demo[useTitle]
import React, { Component, useState, useEffect } from "react";
export const useTitle = (title) => {
useEffect(() => {
document.title = title;
}, [title]);
};
function Counter() {
const [count, setCount] = useState(0);
const incrementCount = () => setCount(count + 1);
useTitle(`You clicked ${count} times`);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={incrementCount}>Click me</button>
</div>
);
}
export default Counter;
- demo[useBoolean]
import { useCallback, useState } from "react";
export const useBoolean = initial => {
const [value, setValue] = useState(initial);
return {
value,
setValue,
toggle: useCallback(() => setValue(v => !v)),
setTrue: useCallback(() => setValue(true)),
setFalse: useCallback(() => setValue(false))
};
};
const App = () => {
const showCounter = useBoolean(true);
return (
<div>
{ showCounter.value ? <h3>Hello</h3> : null }
<button onClick={showCounter.toggle}>Toggle</button>
</div>
)
}
export default App;
- demo[useArray]
import { useCallback, useState } from "react";
export const useArray = initial => {
const [value, setValue] = useState(initial);
return {
value,
setValue,
add: useCallback(a => setValue(v => [...v, a])),
clear: useCallback(() => setValue(() => [])),
removeById: useCallback(id => setValue(arr => arr.filter(v => v && v.id !== id))),
removeIndex: useCallback(index => setValue(v => {v.splice(index, 1); return v; }))
};
};
export const App = () => {
const todos = useArray(["hi there", "sup", "world"]);
return (
<div>
<h3>Todos</h3>
<button onClick={() => todos.add(Math.random())}> add </button>
<ul>
{ todos.value.map((todo, i) => (
<li key={i}> {todo}
<button onClick={() => todos.removeIndex(i)} >delete</button>
</li>
))
}
</ul>
<button onClick={todos.clear}> clear todos </button>
</div>
)
}
- demo[useFormInfo]
import { useCallback, useState } from "react";
export const useFormInfo = (initial) => {
const [value, setParams] = useState(initial);
return {
value,
setParams,
setFiled: useCallback((filed) => (current) => setParams((prev) => ({ ...prev, [filed]: current }))),
setTargetFiled: useCallback((filed) => (e) => setParams((prev) => ({ ...prev, [filed]: e.target?.value }))),
removeFiled: useCallback((filed) => setParams((prev) => delete prev[filed] && prev))
};
};
const getInitial = () => ({
refuseType: null,
refuseReason: null,
name: null
});
export const App = () => {
const refuseInfo = useFormInfo(getInitial());
return (
<div>
<Select
labelInValue
placeholder="请选择理由"
onChange={refuseInfo.setFiled("refuseType")}
options={REFUSE_TYPE_OPTIONS}
/>
<div className="InputBox">
<Input.TextArea
rows={2}
placeholder="输入拒绝理由"
showCount
maxLength={15}
onChange={refuseInfo.setTargetFiled("refuseReason")}
/>
<Input onChange={refuseInfo.setTargetFiled("name")} />
</div>
<div>
<Button onClick={() => {
// refuseInfo.removeFiled('name')
console.log(refuseInfo.value)
}}>提交</Button>
</div>
</div>
)
}
2、useState、useEffect
import React, { useState, useEffect } from "react";
const [count, setCount] = useState(0);
// const [count] = useState(0); // 或者
useEffect(() => {
document.title = `You clicked ${count} times`;
},[count]);
3、useRef、forwardRef、useImperativeHandle
import React, { useRef, useEffect, forwardRef, useImperativeHandle } from "react";
forwardRef(function InputCom({ref}) {
const [open, setOpen] = useState(false)
const [name, setName] = useState(null)
useImperativeHandle(ref, ()=>{
return {
show: () => {
setOpen(true)
},
getValue:()=>{
return ref.current.value||name
}
}
})
return (
<div>
<input
value={name}
type='text'
ref={ref}
onChange=(e=>setName(e.target.value))
/>
<Modal open={open}>
code
</Modal>
</div>
)
})
function App() {
const inpRef = useRef(null)
const focus = () => {
inpRef.current?.focus()
}
const openInput = () => {
inpRef.currnet.show()
}
return (
<div onClick ={openInput} >
<InputCom ref={inpRef} />
</div>
)
}
4、useReducer
- 方案1
import React, { useState } from 'react'
const getInitial = () => ({
refuseType: null,
refuseReason: null,
name: null,
})
const Page: React.FC<IProps> = (props)=> {
const [refuseInfo, setRefuseInfo] = useState(getInitial())
const onChange = (filed, value) => {
return (current)=>{
setRefuseInfo((prev) => {
return {
...prev,
[filed]: current?.target?.value ? current.target.value : current;
}
})
}
}
const getValue = () => refuseInfo
// refuseType, refuseReason, name
return (
<div classNmae="pageWrapper">
<Select
labelInValue
placeholder="请选择理由"
onChange={onChange('refuseType')}
options={REFUSE_TYPE_OPTIONS}
/>
<div className={stl.InputBox}>
<Input.TextArea
ref={reasonRef}
rows={2}
placeholder='输入拒绝理由'
showCount
maxLength={15}
onChange={onChange('refuseReason')}
/>
<Input value={user.name} onChange={onChange('name')} />
</div>
</div>
)
}
- 方案2
import React, { useReducer } from 'react'
const getInitial = () => ({
refuseType: null,
refuseReason: null,
})
const formReducer = (state: any, action: { type: any; value: any }) => {
switch (action.type) {
case 'refuseType':
return {
...state,
refuseType: action.value,
}
case 'refuseReason':
return {
...state,
refuseReason: action.value
}
default:
return state
}
}
const Page: React.FC<IProps> = (props)=> {
const [state, dispatch] = useReducer(formReducer, getInitial())
const getValue = () => state
// refuseType, refuseReason
return (
<div classNmae="pageWrapper">
<Select
labelInValue
placeholder="请选择理由"
onChange={(value)=>dispatch({ type: 'refuseType', value: value.value})}
options={REFUSE_TYPE_OPTIONS}
/>
<div className={stl.InputBox}>
<Input.TextArea
ref={reasonRef}
rows={2}
placeholder='输入拒绝理由'
showCount
maxLength={15}
onChange={(e)=>dispatch({ type: 'refuseReason', value: e.target.value})}
/>
</div>
</div>
)
}
以上内容仅是个人观点,欢迎大家点评修正。