Hooks
:钩子、钓钩、钩住 ,Hooks
是 React v16.8 中的新增功能总结:
componentDidMount
、componentDidUpdate
、componentWillUnmount
this
相关的用法{}
、onClick={handleClick}
、条件渲染、列表渲染、样式处理等单向数据流
、状态提升
等总结:
use
开头useXxx
// 参数:状态初始值(数值、字符串、数组,对象)
// 返回值:stateArray 是一个数组
const stateArray = useState(0);
// 索引 0 表示:状态值(state)
const state = stateArray[0];
// 索引 1 表示:修改状态的函数(setState)
const setState = stateArray[1];
useState
hookuseState
函数,并传入状态的初始值useState
函数的返回值中,拿到状态和修改状态的函数import { useState } from 'react';
const Count = () => {
// stateArray 是一个数组
const stateArray = useState(0);
const state = stateArray[0];
const setState = stateArray[1];
return (
<div>
{/* 展示状态值 */}
<h1>状态为:{state}</h1>
{/* 点击按钮,让状态值 +1 */}
<button onClick={() => setState(state + 1)}>+1</button>
</div>
);
};
import { useState } from 'react';
const Count = () => {
// 解构:
const [count, setCount] = useState(0);
return (
<div>
<h1>计数器:{state}</h1>
<button onClick={() => setState(state + 1)}>+1</button>
</div>
);
};
总结:
给useState
提供初始化值,返回数组。
参考写法:const [count, setCount] = useState(0)
useState
提供的状态,是函数内部的局部变量,可以在函数内的任意位置使const UserCom = () => {
const [user, setUser] = useState({ name: 'jack', age: 18 });
return (
<div>
<p>姓名:{user.name}</p>
<p>年龄:{user.age}</p>
</div>
);
};
setCount(newValue)
是一个函数,参数表示:新的状态值替换
旧值const UserCom = () => {
const [user, setUser] = useState({ name: 'jack', age: 18 });
const onAgeAdd = () => {
setUser({
...user,
age: user.age + 1,
});
};
return (
<div>
<p>姓名:{user.name}</p>
<p>年龄:{user.age}</p>
<button onClick={onAgeAdd}>年龄+1</button>
</div>
);
};
总结:
useState(0)
将传入的参数作为状态初始值,即:0setCount(count + 1)
修改状态,因为状态发生改变,所以,该组件会重新渲染useState(0)
,此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 1import { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<h1>计数器:{count}</h1>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
};
总结:
useState
Hook 多次即可,每调用一次 useState Hook 可以提供一个状态useState Hook
多次调用返回的 [state, setState],相互之间,互不影响可以通过开发者工具进行查看组件的 hooks
总结:
分支循环语句
中,react 存储 hooks 状态按顺序存储。side effect
副作用专业解释总结:
useEffect(() => {
// 书写副作用代码
});
例:count 更新的时候显示到标题
import { useEffect } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `当前已点击 ${count} 次`;
});
return (
<div>
<h1>计数器:{count}</h1>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
};
总结:
useEffect(()=>{})
组件初始化,更新的时候执行useEffect(()=>{})
只要状态发生更新 useEffect 的 effect 回调就会执行useEffect(()=>{},[依赖项])
依赖项的值变化才会执行 effectimport { useEffect } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const [loading, setLoading] = useState(false);
useEffect(() => {
document.title = `当前已点击 ${count} 次`;
}, [count]);
return (
<div>
<h1>计数器:{count}</h1>
<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={() => setCount(!loading)}>切换 loading</button>
</div>
);
};
总结:
useEffect(()=>{},[依赖项])
依赖项可以指定某些状态变化再去执行副作用const App = () => {
const [count, setCount] = useState(0);
// 错误演示:
useEffect(() => {
document.title = '点击了' + count + '次';
}, []);
return (
<div>
<h1>计数器:{count}</h1>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
};
总结:
useEffect(() => {
const handleResize = () => {};
window.addEventListener('resize', handleResize);
}, []);
注意:
componetWillUnmount
useEffect(() => {
const handleResize = () => {};
window.addEventListener('resize', handleResize);
// 这个返回的函数,会在该组件卸载时来执行
// 因此,可以去执行一些清理操作,比如,解绑 window 的事件、清理定时器 等
return () => window.removeEventListener('resize', handleResize);
}, []);
// 1
// 触发时机:1 第一次渲染会执行 2 每次组件重新渲染都会再次执行
// componentDidMount + ComponentDidUpdate
useEffect(() => {});
// 2(使用频率最高)
// 触发时机:只在组件第一次渲染时执行
// componentDidMount
useEffect(() => {}, []);
// 3(使用频率最高)
// 触发时机:1 第一次渲染会执行 2 当 count 变化时会再次执行
// componentDidMount + componentDidUpdate(判断 count 有没有改变)
useEffect(() => {}, [count]);
// 4
useEffect(() => {
// 返回值函数的执行时机:组件卸载时
// 在返回的函数中,清理工作
return () => {
// 相当于 componentWillUnmount
};
}, []);
useEffect(() => {
// 返回值函数的执行时机:1 组件卸载时 2 count 变化时
// 在返回的函数中,清理工作
return () => {};
}, [count]);
use
开头,否则react不认为是 hooks
hook
就是对状态和逻辑的封装,将来可以复用例:
未封装前
App.js
import { useState, useEffect } from "react"
const App = () => {
const [mouse, setMouse] = useState({ x: 0, y: 0 })
useEffect(() => {
const handelMouseMove = (e) => {
setMouse({ x: e.pageX, y: e.pageY })
}
document.addEventListener('mousemove', handelMouseMove)
return () => {
document.removeEventListener('mousemove', handelMouseMove)
}
}, [])
return <div className="app">根组件 {JSON.stringify(mouse)}</div>
}
export default App
封装hooks之后
hook.js
import { useState, useEffect } from "react"
export const useMouse = () => {
const [mouse, setMouse] = useState({ x: 0, y: 0 })
useEffect(() => {
const handelMouseMove = (e) => {
setMouse({ x: e.pageX, y: e.pageY })
}
document.addEventListener('mousemove', handelMouseMove)
return () => {
document.removeEventListener('mousemove', handelMouseMove)
}
}, [])
return mouse
}
App.js
import { useMouse } from "./hooks"
const App = () => {
const mouse = useMouse()
return <div className="app">根组件 {JSON.stringify(mouse)}</div>
}
export default App
使用
useRef
可以获取dom元素,组件也可以通过它获取。
useRef
函数从 react
中const ref = useRef(null)
ref={ref}
绑定ref对象ref.current
获取dom元素例:组件初始化自动获取焦点功能
import { useRef, useEffect } from "react";
const App = () => {
const inputRef = useRef(null);
useEffect(() => {
// input DOM元素
console.log(inputRef.current);
// input 获取焦点
inputRef.current.focus()
}, []);
return (
<div className="app">
根组件:
<input type="text" ref={inputRef} />
</div>
);
};
export default App;
大致步骤:
createContext
创建context对象Provider
组件包裹根组件,注入数据后代
组件中使用 useContext
使用数据通过 createContext
创建context对象
context.js
import { createContext } from "react";
export default createContext({})
通过 Provider
组件包裹根组件,注入数据
App.jsx
import { useState } from "react";
import Context from "./context";
import Child from './Child'
const App = () => {
const [count, setCount] = useState(0)
return (
<Context.Provider value={count}>
<div className="app">
根组件:{count} <button onClick={() => setCount(count + 1)}>打豆豆</button>
<hr />
<Child />
</div>
</Context.Provider>
);
};
export default App;
在 后代
组件中使用 useContext
使用数据
Child.jsx
import { useContext } from "react"
import Context from './context'
const Child = () => {
const count = useContext(Context)
return <div>后代组件:{count}</div>
}
export default Child
总结:
Provider
注入数据和之前一样,使用数据只需要 useContext
即可。!评论内容需包含中文