老师,为什么我写的render执行了两遍,父组件和子组件都打印出了两次
来源:4-3 props,state 与 render 函数的关系
小一_瑶
2020-03-24
TodoList.js
import React, { Component, Fragment } from 'react';
import TodoItem from './TodoItem';
import axios from 'axios'
import './style.css';
class TodoList extends Component {
constructor(props) {
super(props);
// 当组件的state或者props发生改变的时候,render函数就会重新执行
this.state = {
inputValue: '',
list: []
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
}
render() {
console.log('render')
return (
<Fragment>
<div>
<label htmlFor="inputArea">输入内容</label>
<input
id="inputArea"
className="input"
value={this.state.inputValue}
placeholder="请输入内容"
onChange={this.handleInputChange}
/>
<button onClick={this.handleBtnClick}>提交</button>
</div>
<ul>
{ this.getTodoItem() }
</ul>
</Fragment>
)
}
componentDidMount() {
axios.get('/api/todolist')
.then((res)=>{
this.setState(()=>({
list: [...res.data]
}))
}).catch((e)=>{
alert('err')
})
}
getTodoItem() {
return (
this.state.list.map((item, index) => {
return (
<TodoItem
key={item}
content={item}
index={index}
deleteItem={this.handleItemDelete}
>
</TodoItem>
)
})
)
}
handleInputChange(e) {
// setState使用箭头函数时用const常亮将value保存起来
const value = e.target.value;
// const value = this.input.value;
// 性能提升、使用箭头函数变为异步
this.setState(()=>({
inputValue: value
}))
// this.setState({
// inputValue: e.target.value
// })
}
handleBtnClick() {
if (this.state.inputValue.trim() !== '') {
this.setState((prevState)=>({
list: [...this.state.list,prevState.inputValue],
inputValue: ''
}))
// this.setState({
// list: [...this.state.list, this.state.inputValue],
// inputValue: ''
// })
}
}
handleItemDelete(index) {
// immutable 不可直接使用变异方法改变state里的东西
// const list = [...this.state.list];
// list.splice(index, 1);
// this.setState({
// list: list
// })
this.setState((prevState)=>{
const list = [...prevState.list];
list.splice(index, 1);
return { list }
})
}
}
export default TodoList;
TodoItem.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class TodoItem extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this)
}
// 组件更新性能提升
shouldComponentUpdate(nextProps, nextState) {
if(nextProps.content !== this.props.content) {
return true;
} else {
return false
}
}
render() {
console.log('child-render')
const { content } = this.props;
return (
<div onClick={this.handleClick}>
{content}
</div>
)
}
// 一般在这里使用ajax请求
componentDidMount() {
}
handleClick() {
const { deleteItem, index } = this.props;
deleteItem(index)
}
}
TodoItem.propTypes = {
content: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
deleteItem: PropTypes.func,
index: PropTypes.number
}
// 属性默认值
TodoItem.defaultProps = {
}
export default TodoItem
添加axios以后的打印
2回答
-
我也遇到了这个问题,
使用的react版本是16.13.1,入口文件index.js默认使用<React.StrictMode></React.StrictMode>包裹组件,这时render函数会执行两遍,我尝试使用老师的写法,去掉该组件,render函数只会执行一次.
我从react文档中的ADVANCED GUIDES的Strict Mode解释中找到,这应该是严格模式有意重复调用了render函数导致的
https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects
Detecting unexpected side effects
Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following methods:
Class component constructor method
The render method
setState updater functions (the first argument)
The static getDerivedStateFromProps lifecycle
The shouldComponentUpdate method
722020-06-13 -
Dell
2020-03-24
代码发出来我看下,肯定你两次console了
022020-06-06
相似问题