Table of Contents

1、概述

在前面的章节中,我们学习了 props 与 useState,并在上一章的最后一个案例中,为大家演示了父子组件通信的用法。在这一章,我们将进一步说明父子组件通信的注意事项。

父子组件通信是我们在使用 React 时的高频场景,他的表现主要有如下两个

一是子组件在父组件的声明中使用,父组件可以通过 props 将数据传递给子组件

code.ts
1
function Parent() {
2
return <Child name='张三' />
3
}

二是父组件通过 props 传入一个函数,子组件在自己的内部调用该函数,并将子组件内部的状态作为参数传递给该函数,从而实现子组件向父组件通信

code.ts
1
function Parent() {
2
const [name, setName] = useState('张三')
3
const handleClick = (name: string) => {
4
// 在回调函数中,获取从子组件传递过来的数据
5
setName(name)
6
}
7
return <Child name={name} handleClick={handleClick} />
8
}
9
10
function Child({ name, handleClick }: { name: string; handleClick: (name: string) => void }) {
11
function __click() {
12
// 在回调函数中,将数据传递给父组件
13
handleClick('李四')
14
}
15
return <div onClick={__click}>子组件</div>
16
}

2、案例:封装 Input 组件

我们常常会基于 input 元素二次封装一个组件,如下所示。此时我们封装的 Input 组件,在 UI 上明确表示为输入用户名。

预览

在设计上,我们为新的 Input 组件定义了两个 props,分别是 valueonChange。以确保父组件可以向 Input 组件中传入值,并监听 Input 组件的值变化,从而实现父子组件通信。

code.ts
1
interface InputProps {
2
value: string,
3
onChange: (value: string) => void
4
}

完整的 Input 组件代码如下所示

input.tsx
1
import {User} from 'lucide-react'
2
3
interface InputProps {
4
value: string,
5
onChange: (value: string) => void
6
}
7
8
export default function Input({ value, onChange }: InputProps) {
9
return (
10
<div className='flex py-2 px-4 items-center max-w-96 gap-2 border border-gray-300 rounded-xl dark:border-0 dark:inset-ring dark:inset-ring-white/10'>
11
<div className='flex flex-col flex-1'>
12
<div className='text-sm text-gray-500 pl-2'>用户名</div>
13
<input
14
type="text"
15
className='outline-none !border-0 m-0'
16
value={value}
17
onChange={e => onChange(e.target.value)}
18
placeholder='请输入用户名'
19
/>
20
</div>
21
<User size={20} />
22
</div>
23
)
24
}

在父组件中,我们可以则直接使用 Input 组件,并监听其值的变化即可。此时我们可以看到,在父组件的其他 UI 部分,就可以拿到在子组件中输入的值

index.tsx
1
import { useState } from 'react'
2
import Input from './input'
3
4
export default function Parent() {
5
const [value, setValue] = useState('')
6
7
return (
8
<div>
9
<Input value={value} onChange={setValue} />
10
<div className='mt-4 text-sm'>
11
用户名为:{value}
12
</div>
13
</div>
14
15
)
16
}

3、总结

在后续的学习中,关于父子组件通信,我们还要学习受控组件与非受控组件的概念。这会在学习了 useEffect 后,为大家详细说明。

专栏首页
到顶
专栏目录