一.useState
useState 是一个 React Hook(函数),它允许我们向组件添加一个状态变量, 从而控制影响组件的渲染结果
本质:和普通JS变量不同的是,状态变量一旦发生变化组件的视图UI也会跟着变化**(数据驱动视图)**
const [count, setCount] = useState(0)
- useState是一个函数,返回值是一个数组
- 数组中的第一个参数是状态变量,第二个参数是set函数用来修改状态变量
- useState的参数将作为count的初始值
1.1 修改状态的规则
状态不可变
在React中,状态被认为是只读的,我们应该始终替换它而不是修改它,直接修改状态不能引发视图更新
let [count, setCount] = useState(0)
const handleClick = () => {
// 直接修改 无法引发视图更新
// count++
// console.log(count)
setCount(count + 1)
}
class组件中this.setState更新是state是合并, hook中 useState中setState是替换
修改对象状态
// 修改对象状态
const [form, setForm] = useState({ name: 'jack' })
const changeForm = () => {
// 错误写法:直接修改 不引发视图变化
// form.name = 'john'
// 正确写法:setFrom 传入一个全新的对象
setForm({
...form,
name: 'john'
})
}
二.受控表单绑定
vue中的双向数据绑定
// 1. 通过value属性绑定react状态
// 2. 绑定onChange事件 通过事件参数e拿到输入框最新的值 反向修改到react状态身上
function App () {
const [value, setValue] = useState('')
return (
<div>
<input
value={value}
onChange={(e) => setValue(e.target.value)}
type="text" />
</div>
)
}
三. React中获取DOM
在 React 组件中获取/操作 DOM,需要使用 useRef React Hook钩子函数
- 使用useRef创建 ref 对象,并与 JSX 绑定
- 在DOM可用时,通过 inputRef.current 拿到 DOM 对象
// 1. useRef生成ref对象 绑定到dom标签身上
// 2. dom可用时,ref.current获取dom
// 渲染完毕之后dom生成之后才可用
function App () {
const inputRef = useRef(null)
const showDom = () => {
console.dir(inputRef.current)
}
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={showDom}>获取dom</button>
</div>
)
}
四. 组件通信
4.1 父传子-props
props可传递任意的数据
数字、字符串、布尔值、数组、对象、函数、JSX
<Son
name={name}
age={18}
isTrue={false}
list={['vue', 'react']}
obj={{ name: 'jack' }}
cb={() => console.log(123)}
child={<span>this is span</span>}
>
<p>33</p>
</Son>
子组件只能读取props中的数据,不能直接进行修改, 父组件的数据只能由父组件修改
4.2 子传父
核心思路:在子组件中调用父组件中的函数并传递参数
<Son onGetSonMsg={getMsg} />
<div>
this is Son
<button onClick={() => onGetSonMsg('this is son msg')}>sendMsg</button>
</div>
4.3.兄弟组件通信
使用状态提升实现兄弟组件通信
- A组件先通过子传父的方式把数据传给父组件App
- App拿到数据后通过父传子的方式再传递给B组件
4.4.跨层传递数据
使用Context机制跨层级组件通信
实现步骤:
- 使用createContext方法创建一个上下文对象Ctx
- 在顶层组件(App)中通过 Ctx.Provider 组件提供数据
- 在底层组件(B)中通过 useContext 钩子函数获取消费数据
// App -> A -> B
import { createContext, useContext } from "react"
// 1. createContext方法创建一个上下文对象
const MsgContext = createContext()
// 2. 在顶层组件 通过Provider组件提供数据
// 3. 在底层组件 通过useContext钩子函数使用数据
function App () {
const msg = 'this is app msg'
return (
<div>
<MsgContext.Provider value={msg}>
this is App
<A />
</MsgContext.Provider>
</div>
)
}
function A () {
return (
<div>
this is A component
<B />
</div>
)
}
function B () {
const msg = useContext(MsgContext)
return (
<div>
this is B compnent,{msg}
</div>
)
}