一、useState的使用
1. 基础使用
useState是一个React Hook(函数),它允许我们向组件添加一个状态变量,从而控制影响组件的渲染结果。
状态变量一旦发生变化组件的视图UI也会跟着变化(数据驱动视图)
const [count, setCount] = useState(0);
- useState是一个函数,返回值是一个数组;
- 数组中第一个参数是状态变量,第二个参数是set函数用来修改状态变量;
- useState的参数将作为状态变量的初始值;
setCount(count+1);
作用:
- 用传入的新值修改
count
; - 重新使用新的
count
渲染UI;
2. 修改状态的规则
状态不可变:在React中,状态被认为是只读的,我们应该始终替换它而不是修改它,直接修改状态不能引发视图更新。
修改对象状态:
const [form, setForm] = useState({
name: 'jack',
})
const handleChangeName = () => {
// form.name = 'john'
setForm({
...form,
name: 'john',
})
}
二、组件的基础样式处理
React组件基础的样式控制有两种方式:
-
行内样式
<div style={{ color: 'red' }}>this is div</div>
-
class类名控制
.foo { color: red; } <span className="foo">this is span</span>
三、React表单控制
1. 受控绑定
使用React组件的状态(useState)控制表单的状态。
function App() {
const [value, setValue] = useState('');
return (
<input
type="text"
value={value} {/*通过value属性绑定react状态*/}
// 绑定onChange事件 通过事件参数e拿到输入框最新的值,
// 反向修改到react状态
onChange={e => setValue(e.target.value)}
/>
)
}
2. 非受控绑定
通过获取DOM的方式获取表单的输入数据。
function App() {
// 1. useRef生成ref对象,绑定到DOM上
const inputRef = useRef(null);
const onChange = () => {
// 2. DOM可用时(即DOM渲染完毕后),使用ref.current获取DOM
console.log(inputRef.current.value);
}
return (
<input
type="text"
ref={inputRef}
onChange={onChange}
/>
)
}
四、React组件通信
组件通信就是组件之间的数据传递,根据组件嵌套关系的不同,有不同的通信手段和方法。
1. 父子通信-父传子
1.1 基础实现
实现步骤:
- 父组件传递数据 - 在子组件标签上绑定属性
- 子组件接收数据 - 子组件通过props参数接收数据
function Son(props) {
return <div>{ props.name }</div>
}
function App() {
const name = 'this is app name'
return (
<div>
<Son name={name} />
</div>
)
}
1.2 props的使用
props可以传递任意的合法数据,如数字、字符串、布尔值、数组、对象、函数、JSX。
props是只读对象,子组件只能读取props中的数据,不能直接进行修改,父组件的数据只能由父组件修改。
当我们把内容嵌套在组件的标签内部时,组件会自动在名为children的prop属性中接收该内容。
<Son>
<span>this is son</span>
</Son>
// Son组件的props上会有children属性
// props:
// children: <span />
2. 父子通信-子传父
核心思路:在子组件中调用父组件中的函数并传递参数
function Son({ onGetMsg }){
const sonMsg = 'this is son msg';
return (
<div>
{/* 在子组件中执行父组件传递过来的函数 */}
<button onClick={() => onGetMsg(sonMsg)}>send</button>
</div>
)
}
function App() {
const [msg, setMsg] = useState('');
const getMsg = (msg) => {
setMsg(msg);
console.log(msg);
}
return (
<div>
{/* 传递父组件中的函数到子组件 */}
<Son onGetMsg={ getMsg }/>
{msg}
</div>
)
}
3. 兄弟组件通信
实现思路:借助状态提升机制,通过共同的父组件进行兄弟之间的数据传递。
- A组件先通过子传父的方式把数据传递给父组件App
- App拿到数据之后通过父传子的方式再传递给B组件
// 1.通过子传父 A -> App
// 2.通过父传子 App -> B
function A({onGetAName}) {
// A组件中的数据
const name = 'this is A name'
return (
<div>
this is A component,
<button onClick={() => onGetAName(name)}>send</button>
</div>
)
}
function B({name}) {
return (
<div>
this is B component,
{name}
</div>
)
}
function App() {
const [name, setName] = useState('');
const getAName = (name) => {
setName(name);
}
return (
<div>
<A onGetAName={getAName} />
<B name={name} />
</div>
)
}
4. 跨层组件通信
步骤:
- 使用
createContext
方法创建一个上下文对象Ctx
- 在顶层组件(App)中通过
Ctx.Provider
组件提供数据 - 在底层组件(B)中通过
useContext
钩子函数获取消费数据
// App -> A -> B
import { createContext, useContext } from "react";
// 1.使用createContext方法创建一个上下文对象
const MsgContext = createContext();
function A() {
return (
<div>
this is A component
<B />
</div>
)
}
function B() {
// 3.在底层组件中通过useContext钩子函数使用数据
const msg = useContext(MsgContext);
return (
<div>
this is B component, {msg}
</div>
)
}
function App() {
const msg = 'this is app msg';
return (
<div>
{/* 2.在顶层组件中通过Provider组件提供数据 */}
<MsgContext.Provider value={msg}>
this is App
<A />
</MsgContext.Provider>
</div>
)
}
export default App;
五、React副作用管理-useEffect
useEffect
是一个React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作(副作用),如发送ajax请求,更改DOM等。
useEffect(
() => {}, // 第一个参数是一个函数,在函数内部放置要执行的操作
[] // 第二个参数是一个数组(可选参),在数组中放置依赖项
)
1. 依赖说明
依赖项 | 副作用函数的执行时机 |
---|---|
没有依赖项 | 组件初始渲染 + 组件更新时执行 |
空数组依赖 | 只在初始渲染时执行一次 |
添加特定依赖项 | 组件初始渲染 + 依赖项变化时执行 |
2. 清除副作用
在useEffect中编写的由渲染本身引起的对接组件外部的操作,如定时器,想在组件卸载时清除定时器,这个过程就是清理副作用。
useEffect(() => {
// 实现副作用操作逻辑
return () => {
// 清除副作用逻辑
}
})
六、自定义Hook实现
自定义Hook是以use
开头的函数,通过自定义Hook函数可以用来实现逻辑的封装和复用。
1. 通用思路
- 声明一个以use开头的函数
- 在函数体内封装可复用的逻辑
- 在组件中用到的状态或者回调return出去(以对象或数组)
- 在哪个组件中要用到这个逻辑,就执行这个函数,解构出来状态和回调进行使用
function useToggle() {
// 可复用的逻辑代码
const [value, setValue] = useState(true);
const toggle = () => setValue(!value);
// 哪些状态和回调函数需要在其他组件中使用 return
return {
value,
toggle
}
}
function App() {
const { value, toggle } = useToggle();
return (
<div>
{value && <div>this is div</div>}
<button onClick={toggle}>toggle</button>
</div>
)
}
2. 使用规则
- 只能在组件中或者其他自定义Hook函数中调用
- 只能在组件的顶层调用,不能嵌套在if、for、其它的函数中