Props 和 State 的主要区别
- 数据流向:
- Props:是单向数据流,从父组件传递到子组件。父组件控制子组件接收到的 props 值,子组件不能直接修改接收到的 props。这使得数据流动清晰,便于追踪和调试。
- State:是组件内部的状态,其变化只影响当前组件本身。组件可以根据用户交互、网络请求等事件自行修改 state,进而触发组件重新渲染。
- 数据来源:
- Props:来自父组件的传递,是外部传入的数据。例如,父组件有一个列表,要将列表中的某一项数据传递给子组件展示,就通过 props 传递。
- State:组件自身维护的数据,用于记录组件内部的变化。比如一个按钮的点击次数,这个数据只在组件内部有意义,就可以用 state 来维护。
- 是否可变:
- Props:对于接收 props 的子组件来说是只读的,不可变。如果需要修改,必须由父组件更新后重新传递。
- State:可以在组件内部通过
setState
(类组件)或 useState
(函数组件)方法进行修改,每次修改都会触发组件的重新渲染。
实际场景举例
- 使用 Props 的场景:
- 组件复用:例如有一个
Button
组件,父组件可以通过 props 传递不同的 text
(按钮显示的文本)、color
(按钮颜色)等属性,使这个 Button
组件在不同地方展示不同样式和功能。如下代码:
// 父组件
import React from'react';
import Button from './Button';
function ParentComponent() {
return (
<div>
<Button text="提交" color="blue" />
<Button text="取消" color="red" />
</div>
);
}
export default ParentComponent;
// Button 子组件
import React from'react';
function Button({ text, color }) {
return <button style={{ backgroundColor: color }}>{text}</button>;
}
export default Button;
- 数据传递:在一个树形结构的菜单组件中,父菜单组件将菜单项数据通过 props 传递给子菜单组件,子菜单组件根据接收到的 props 展示具体的菜单项。
- 使用 State 的场景:
- 用户交互:比如一个输入框组件,用户输入内容时,组件需要实时记录输入的值,就可以使用 state。如下代码:
import React, { useState } from'react';
function InputComponent() {
const [inputValue, setInputValue] = useState('');
const handleChange = (e) => {
setInputValue(e.target.value);
};
return (
<div>
<input value={inputValue} onChange={handleChange} />
<p>你输入的内容是: {inputValue}</p>
</div>
);
}
export default InputComponent;
- 异步操作状态:在一个图片加载组件中,使用 state 来记录图片加载状态(loading、loaded、error)。在图片开始加载时设置 state 为
loading
,加载成功设置为 loaded
,加载失败设置为 error
,并根据不同的 state 展示不同的 UI。
import React, { useState, useEffect } from'react';
function ImageLoader() {
const [imageState, setImageState] = useState('loading');
useEffect(() => {
const img = new Image();
img.onload = () => {
setImageState('loaded');
};
img.onerror = () => {
setImageState('error');
};
img.src = 'your - image - url.jpg';
}, []);
return (
<div>
{imageState === 'loading' && <p>加载中...</p>}
{imageState === 'loaded' && <img src="your - image - url.jpg" />}
{imageState === 'error' && <p>图片加载失败</p>}
</div>
);
}
export default ImageLoader;