这篇文章主要回答如下个问题:
- 如何实现一个带参数的React组件
- 如何设置可选参数,并为参数设置默认值。这里ts和js有些不同
- parent的state,通过props传递给组件后,是否可以双向修改?
如何实现一个带参数的React组件
这个问题,官方文档给了一个简单的js例子
function Avatar(props) {
let person = props.person;
let size = props.size;
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
或者可以直接利用解构赋值,写成下面的形式:
function Avatar({ person, size }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
利用typescript大致是一样的, 只是需要执行参数的Type
interface AvatarProps {
person: {
name: string,
imageId: string,
},
size: number
}
function Avatar({ person, size }: AvatarProps) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
使用起来ts和js都是一样的:
<Avatar person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} size={100} />
如何设置可选参数,并为参数设置默认值
设置可选参数,对Javascript是比较直接的,直接在组件参数中给可选参数设置默认值即可:
function Avatar({ person, size = 100 }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
这样,在使用Avatar
组件的时候,可以不指定size,使用默认值。
对于Typescript,除了为可选参数设置默认值以外,在interface
中也要做修改,在参数名后加个?
interface AvatarProps {
person: {
name: string,
imageId: string,
},
size?: number
}
function Avatar({ person, size = 100 }: AvatarProps) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
parent的state,通过props传递给组件后,是否可以被修改
这个问题可以分成两种情况:
- 在parent中修改state,组件中的参数会发生改变吗?
- 在组件中修改参数,parent中的state会发生改变吗?
关于这个问题,官方文档特意说明,props是“不可修改“的:
props are immutable—a term from computer science meaning “unchangeable”. When a component needs to change its props (for example, in response to a user interaction or new data), it will have to “ask” its parent component to pass it different props—a new object! Its old props will then be cast aside, and eventually the JavaScript engine will reclaim the memory taken by them.
那下面代码的效果会是什么样呢?
import {useState} from 'react'
function Avatar({ person, size, setSize }) {
return (
<div>
<button onClick={(e)=>{setSize(size-100)}}>减小size</button>
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
</div>
);
}
export default function Profile() {
const [size, setSize] = useState(100)
return (
<div>
<button onClick={(e)=>{setSize(size+100)}}>增大size</button/>
<div>{size}</div>
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={size}
setSize={setSize}
/>
</div>
);
}
答案是图片size可以变大/变小
也就是说,上面两个问题的答案都是yes。