老师,为什么我写的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回答

floppyfish

2020-03-28

我也遇到了这个问题,

使用的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


7
2
Whitney_Wang
感谢!
2020-06-13
共2条回复

Dell

2020-03-24

代码发出来我看下,肯定你两次console了

0
2
慕粉2320486108
新提出严格模式比之前的非严格模式有什么明显的优点吗,老师推荐在现在要使用严格模式吗
2020-06-06
共2条回复

React零基础入门到实战,完成企业级项目简书网站开发

主流新技术 React-redux,React-router4,贯穿基础语法

5275 学习 · 2496 问题

查看课程