React组件的state和props
React组件的state和props
React的数据是自顶向下单向流动的,即从父组件到子组件中,组件的数据存储在props和state中。实际上在任何应用中,数据都是必不可少的,我们需要直接的改变页面上一块的区域来使得视图的刷新,或者间接地改变其他地方的数据,在React中就使用props和state两个属性存储数据。
描述
state的主要作用是用于组件保存、控制、修改自己的可变状态。state在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修改,可以认为state是一个局部的、只能被组件自身控制的数据源,state中状态可以通过this.setState方法进行更新,setState会导致组件的重新渲染。
props的主要作用是让使用该组件的父组件可以传入参数来配置该组件,它是外部传进来的配置参数,组件内部无法控制也无法修改,除非外部组件主动传入新的props,否则组件的props永远保持不变。
state和props都可以决定组件的行为和显示形态,一个组件的state中的数据可以通过props传给子组件,一个组件可以使用外部传入的props来初始化自己的state,但是它们的职责其实非常明晰分明,state是让组件控制自己的状态,props是让外部对组件自己进行配置。简单来说props是传递给组件的(类似于函数的形参),而state是在组件内被组件自己管理的(类似于在一个函数内声明的变量)。
一个清晰的原则是尽量少地用state,尽量多地用props,没有state的组件叫无状态组件stateless component,设置了state的叫做有状态组件stateful component。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件,这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。
props
React的核心思想就是组件化思想,页面会被切分成一些独立的、可复用的组件。组件从概念上看就是一个函数,可以接受一个参数作为输入值,这个参数就是props,所以可以把props理解为从外部传入组件内部的数据,由于React是单向数据流,所以props基本上也就是从服父级组件向子组件传递的数据。
假设我们现在需要实现一个列表,我们把列表中的行当做一个组件,也就是有这样两个组件<ItemList/>和<Item/>。列表ItemList组件的数据我们就暂时先假设是放在一个data变量中,然后通过map函数返回一个每一项都是<Item item={数据}/>的数组,也就是说这里其实包含了data.length个<Item/>组件,数据通过在组件上自定义一个参数传递。之后在Item组件内部是使用this.props来获取传递到该组件的所有数据,它是一个对象其中包含了所有对这个组件的配置,现在只包含了一个item属性,所以通过this.props.item来获取即可。
// Item组件
class Item extends React.Component{
render(){
return (
<li>{this.props.item}</li>
)
}
}
// ItemList组件
class ItemList extends React.Component{
render(){
const data = [1, 2, 3, 4, 5, 6];
const itemList = data.map((v, i) => <Item item={v} key={i}/>);
return (
<ul>{itemList}</ul>
)
}
}
props经常被用作渲染组件和初始化状态,当一个组件被实例化之后,它的props是只读的,不可改变的。如果props在渲染过程中可以被改变,会导致这个组件显示的形态变得不可预测,只有通过父组件重新渲染的方式才可以把新的props传入组件中。也就是说props是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的props来重新渲染子组件,否则子组件的props以及展现形式不会改变。
在组件中,我们也可以为props中的参数设置一个defaultProps,并且制定它的类型。
import PropTypes from "prop-types";
class Hello extends React.Component{
constructor(props){
super(props);
}
render() {
return (
<div>{this.props.tips}</div>
);
}
}
Hello.propTypes = {
tips: PropTypes.string
};
不同的验证器类型如下。
import PropTypes from "prop-types";
MyComponent.propTypes = {
// JS原始类型,这些全部默认是可选的
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 可以直接渲染的任何东西,可以是数字、字符串、元素或数组
optionalNode: PropTypes.node,
// React元素
optionalElement: PropTypes.element,
// 指定是某个类的实例
optionalMessage: PropTypes.instanceOf(Message),
// 可以是多个值中的一个
optionalEnum: PropTypes.oneOf(["News", "Photos"]),
// 可以是多种类型中的一个
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// 只能是某种类型的数组
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// 具有特定类型属性值的对象
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// 具有相同属性值的对象
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// 必选条件,可以配合其他验证器,以确保在没有提供属性的情况下发出警告
requiredFunc: PropTypes.func.isRequired,
// 必选条件,提供的属性可以为任意类型
requiredAny: PropTypes.any.isRequired,
// 自定义 oneOfType 验证器。如果提供的属性值不匹配的它应该抛出一个异常
// 注意:不能使用 console.warn 和 throw
customProp: function(props, propName, componentName) {
if (!/matcher/.test(props[propName])) {
return new Error("Not Match");
}
},
// 自定义 arrayOf 或者 objectOf 验证器。
// 它会调用每个数组或者对象的key,参数前两个是对象它本身和当前key
// 注意:不能使用 console.warn 和 throw
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matcher/.test(propValue[key])) {
return new Error("Not Match");
}
})
};
state
一个组件的显示形态可以由数据状态和外部参数所决定,外部参数也就是props,而数据状态就是state。state的主要作用是用于组件保存、控制以及修改自己的状态,它只能在constructor中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的this.setState来修改,修改state属性会导致组件的重新渲染。简单来说就是在组件初始化的时候,通过this.state给组件设定一个初始的state,在第一次render的时候就会用这个数据来渲染组件。
class Hello extends React.Component{
constructor(props){
super(props);
this.state = {
tips: "Hello World!"
}
}
render() {
return (
<div>{this.state.tips}</div>
);
}
}
state不同于props的一点是,state是可以被改变的。不过不可以直接通过this.state= values;的方式来修改,而需要通过this.setState()方法来修改state。例如我们经常会通过异步操作来获取数据,我们需要在didMount生命周期阶段来执行异步操作。
componentDidMount(){
fetch("url")
.then(response => response.json())
.then((data) => {
this.setState({itemList:item});
}
}
当我们调用this.setState方法时,React会更新组件的数据状态state,并且重新调用render方法,也就是会对组件进行重新渲染。setState接受一个对象或者函数作为第一个参数,只需要传入需要更新的部分即可,setState还可以接受第二个参数,它是一个函数,会在setState调用完成并且组件开始重新渲染时被调用,可以用来监听渲染完成。
this.setState({ tips: "data update" });
this.setState({ tips: "data update" }, () => console.log("finished"));
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React</title>
</head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
class Item extends React.Component{
render(){
return (
<li>{this.props.item}</li>
)
}
}
class ItemList extends React.Component{
render(){
const data = [1, 2, 3, 4, 5, 6];
const itemList = data.map((v, i) => <Item item={v} key={i}/>);
return (
<ul>{itemList}</ul>
)
}
}
class Hello extends React.Component{
constructor(props){
super(props);
this.state = {
tips: "Hello World!"
}
}
render() {
return (
<div>{this.state.tips}</div>
);
}
}
class App extends React.Component{
render() {
return (
<div>
<Hello />
<ItemList />
</div>
);
}
}
var vm = ReactDOM.render(
<App />,
document.getElementById("root")
);
</script>
</html>
每日一题
https://github.com/WindrunnerMax/EveryDay
参考
https://github.com/axuebin/react-blog/issues/8
https://zh-hans.reactjs.org/docs/faq-state.html
http://huziketang.mangojuice.top/books/react/lesson12
React组件的state和props的更多相关文章
- 说说React组件的State
说说React组件的State React的核心思想是组件化的思想,应用由组件搭建而成, 而组件中最重要的概念是State(状态). 正确定义State React把组件看成一个状态机.通过与用户的交 ...
- React组件的State
React组件的State 1.正确定义State React把组件看成一个状态机.通过与用户的交互,实现不同状态,然后渲染UI,让用户界面和数据保持一致.组件的任何UI改变,都可以从State的变化 ...
- React组件三大属性之 props
React组件三大属性之 props 理解1) 每个组件对象都会有props(properties的简写)属性2) 组件标签的所有属性都保存在props中 作用1) 通过标签属性从组件外向组件内传递变 ...
- React中的state与props的再理解
props可以看做是 property 的缩写的复数,可以翻译为属性,类似于HTML 标签的自定义属性.在大多数React教程里讲 state 和 props 主要的区别在于 props 是不可变的, ...
- React中的State与Props
一.State 1.什么是 state 一个组件的显示形态可以由数据状态和外部参数决定,其中,数据状态为 state,外部参数为 props 2.state 的使用 组件初始化时,通过 this.st ...
- 表单组件中state依赖props
参阅避免派生状态的博文: https://zh-hans.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
- React中state和props分别是什么?
整理一下React中关于state和props的知识点. 在任何应用中,数据都是必不可少的.我们需要直接的改变页面上一块的区域来使得视图的刷新,或者间接地改变其他地方的数据.React的数据是自顶向下 ...
- 野心勃勃的React组件生命周期
当你还在写着Angular指令,过滤器,注入,服务,提供者,视图模版的时候,是不是觉得很烦,好在这个时候,React已经神一样的出现在历史舞台. React组件 React实现了UI=Fn(St ...
- React——组件的生命周期函数
每一个组件都有一些生命周期函数. 当组件实例被创建并且会插入到DOM中,下面这些函数会被调用 constructor componentWillMount render componentDidMou ...
随机推荐
- LeetCode周赛#205
5508. 数的平方等于两数乘积的方法数 #模拟 #哈希表 题目链接 题意 给你两个整数数组nums1 和 nums2 ,请你返回根据以下规则形成的三元组的数目(类型 1 和类型 2 ): 类型 1: ...
- Java基础教程——解析注解
解析注解 Java 5开始,java.lang.reflect包下的反射API可以在运行时读取Annotation. 应用:定义一个自动执行方法的注解,解析注解.通过反射执行方法,替代配置文件. pa ...
- 怎么用fio测试存储性能
1 /// -rw=read(100%顺序读) -rw=write(100%顺序写) -rw=randread(100%随机读) -rw=randwrite(100%随机写), 2 ///-rw=rw ...
- 蒲公英 · JELLY技术周刊 Vol.32: 前端的自我进化之路
蒲公英 · JELLY技术周刊 Vol.32 前端开发不过是切图仔在那儿瞎鼓捣,没啥门槛,不需要懂计算机原理,不需要懂算法,微服务.高并发这些都不需要懂,拖组件写个页面就好了,数据.逻辑.测试都可以交 ...
- 关于将Linux中默认的OpenJDK替换为JDK的方法
首先下载需要的jdk安装包,后缀建议.tar.gz,本文中以jdk-8u212-linux-x64.tar.gz为例,地址就在oracle官网. 将安装包下载到linux环境后,使用命令tar -xz ...
- PHP代码审计分段讲解(2)
03 多重加密 源代码为: <?php include 'common.php'; $requset = array_merge($_GET, $_POST, $_SESSION, $_COOK ...
- LeetCode初级算法之数组:1 两数之和
两数之和 题目地址:https://leetcode-cn.com/problems/two-sum/ 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整 ...
- 漫话docker的衰落与kubernetes的兴起
本文首发在OPPO互联网公众号,欢迎点击转载 https://mp.weixin.qq.com/s/wBC4CgAzXeTNURa1YdYmIQ. 伴随着kubernetes 1.20中对于docke ...
- 认识css常见的hack
一.认识css hack CSS Hack只要是来解决浏览器局部的兼容性问题,主要是因为每个浏览器对css的解析各不相同,导致输出到页面的效果的差异: 二.css hack的三种常见形式:css属性h ...
- 使用MySQL乐观锁解决超卖问题
在秒杀系统设计中,超卖是一个经典.常见的问题,任何商品都会有数量上限,如何避免成功下订单买到商品的人数不超过商品数量的上限,这是每个抢购活动都要面临的难点. 1 超卖问题描述 在多个用户同时发起对同一 ...