为什么我的渲染方法被调用两次

时间:2020-04-30 20:45:14

标签: reactjs

enter image description here我是新来的人,可以做出反应并进行还原。对我来说这是一个令人困惑的问题。有人可以解释一下为什么每次输入更改后我的searchTerm状态值打印两次(渲染方法被调用两次)的原因。我读了React,了解到在每个状态更改中,都会调用render,但是在此状态中,render被调用了两次?我搞错了吗?

App.js

import React from 'react';
import Todos from './components/Todos';
import Header from './components/Header';

class App extends React.Component {
state = {
    searchTerm : '',
    todos: [{
    id: 1,
    completed: true,
    text: "I am number one"
    }, 
{
    id: 2,
    completed: false,
    text: "I am number two"
},
{
    id: 3,
    completed: false,
    text: "I am number three"
}]
}

markComplete = (id) => {
    this.setState({
    todos: this.state.todos.map(todo => {
        if (todo.id === id) {
        todo.completed = !todo.completed;
        }
        return todo;
    })
    });
}

deleteTo = (id) => {
    this.setState({
    todos: [...this.state.todos.filter(todo => todo.id!==id)]
    });
}

search = (evt) => {
    const value = evt.target.value;
    this.setState({
    searchTerm: value
    });
}

render() {
    return (
    <div>
        <Header />
        { console.log(this.state.searchTerm) }
        <input type="text" onChange = {this.search} />         
        <Todos todos = {this.state.todos} markComplete = {this.markComplete} deleteTo = {this.deleteTo}/>
    </div>
    );
}
}

export default App;

Todos.js

import React, { Component } from 'react';
import TodoItem from './TodoItem';

class Todos extends Component {

render() {
    return this.props.todos.map((todo) => 
    <TodoItem key={todo.id} todo = {todo} markComplete = {this.props.markComplete} deleteTo={this.props.deleteTo}/>)
}
}

export default Todos;

TodoItem.js

import React, { Component } from 'react';

class TodoItem extends Component {

getStyle = () => {
    return { textDecoration: this.props.todo.completed ? "line-through": "none" };
};

getButtonStyle = () => {
    return {
        backgroundColor: 'red',
        border: 'none',
        cursor: 'pointer',
        float: 'right',
        padding: '5px 10px',
        borderRadius: '50%'
    };
}

render() {
    const {id, text} = this.props.todo;

    return ( 
    <div style={this.getStyle()}>
        <p>
        <input type="checkbox" onChange= { () => this.props.markComplete(id) }/> {' '}
        {text} 
        <button style={this.getButtonStyle()} onClick = { () => this.props.deleteTo(id)}> x </button>
        </p>
    </div>
    );
}
}

export default TodoItem;

3 个答案:

答案 0 :(得分:2)

componentDidUpdate函数在落实阶段发生之前几乎可以被调用任何次,并且更新被刷新到DOM。 render函数也应该是一个纯函数,这意味着没有副作用,例如控制台日志记录。而是使用 set consoleName="hello" set batch=echo foo start "%consoleName%" /max %batch% cmd.exe 生命周期函数记录状态或道具更新的时间。也许这张图会有所帮助。

enter image description here

答案 1 :(得分:0)

这可能是因为 index.js 文件中的React StrictMode (如果使用create-react-app)。

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
serviceWorker.unregister();

严格模式检查潜在问题,并导致两次运行某些生命周期方法(例如构造函数,渲染,componentShouldUpdate等)。

严格模式检查仅在开发模式下运行;它们不会影响生产。

您可以在strict-mode

上了解更多信息

答案 2 :(得分:0)

避免副作用的一个简单解决方案是不在 Render() 中分配动态值,只需保持状态 ,并在 Render() 之前调用它作为 Click() 方法的示例。