react useContext useReducer≈redux
父组件
const intialState = { count: 0 }
const reducer = (state, action) => {
switch(action.type) {
case "ADD":
return { ...state, count: action.count }
default:
return state
}
}
export default () => {
const Context = React.createContext(null)
const [state, dispatch] = useReducer(reducer, intialState)
return (
<Context.Provider value={{ state, dispatch }}>
<Child Context={Context}/>
</Context.Provider>
)
}
子组件
export default ({ Context }) => {
const { state, dispatch } = useReducer(Context)
return (
<div onClick={() => {
dispatch({ type: "ADD", payload:state.count + 1 })
}}>
{state.count}
</div>
)
}
setState批量更新在setTimeout函数中失效,导致useEffect设定函数执行两边
对于useReducer生成的dispatch事件的情况同样如此
特别注意lodash.debounce函数的使用,因为他的实现原理就是setTimeout
function App() {
const [count, setCount] = useState(0)
const [time, setTime] = useState(0)
useEffect(() => {
console.log(1111);
}, [count, time])
// 只打印一遍111
const clickOne = () => {
setCount(count + 1)
setTime(time + 1)
}
// 打印两遍111,可以理解为App函数执行了两遍,因为这两个set都是建立了自己的函数执行空间
const clickTwo = () => {
setTimeout(() => {
setCount(count + 1)
setTime(time + 1)
}, 1000)
}
// 还是打印两遍111,不理解
const clickThree = () => {
setTimeout(() => {
const fn = () => {
setCount(count + 1)
setTime(time + 1)
}
fn()
}, 1000)
}
return (
<div>
<div onClick={clickOne}>正常点击</div>
<div onClick={clickTwo}>setTimeout点击</div>
<div onClick={clickThree}>setTimeout合并set点击</div>
</div>
)
}
export default App
lodash.debounce在hooks中失效问题
使用useCallback缓存函数解决此问题
function App() {
const [count, setCount] = useState(0)
// 点击失效点击按钮时,如果中途执行过set方法,函数会重新执行一遍,生成一个新的clickOne函数
// 那么此时的防抖就失效了,因为防抖需要保证的是函数永远是同一个,才能清除之前函数
const clickOne = debounce(() => {
console.log(1111);
}, 3000)
// 此时相当于缓存了clickTwo函数,此方法永远是同一个函数,不会在App函数执行过程中更新
// 那么debounce就能生效
const clickTwo = useCallback(debounce(() => {
console.log(22222);
}, 3000), [])
const clickThree = () => {
setCount(count + 1)
}
return (
<div>
<br />
<div onClick={clickOne}>失效点击</div>
<div onClick={clickTwo}>生效debounce点击</div>
<div onClick={clickThree}>辅助测试点击{count}</div>
</div>
)
}
条件渲染
在 JavaScript 中,true && expression 总是会返回 expression, 而 false && expression 总是会返回 false。
因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。
请注意,返回 false 的表达式会使 && 后面的元素被跳过,但会返回 false 表达式。在下面示例中,render 方法的返回值是
0
。
render() {
const count = 0;
return (
<div>
{ count && <h1>Messages: {count}</h1>}
</div>
);
}