【问题标题】:Console.log() after setState() doesn't return the updated statesetState() 之后的 Console.log() 不返回更新的状态
【发布时间】:2019-07-09 20:15:09
【问题描述】:

我创建了一个简单的待办事项列表来学习反应,我正在尝试添加一些额外的功能。目前我正在尝试添加切换项目列表的按钮,因此它要么显示所有任务,要么只显示已完成的任务。

我编写了一个函数来更改我的 visabilityFilter 的状态,以便以后可以使用它来切换列表中的项目,但它的行为不应该是这样。

我在控制台记录了 visabilityFilter 变量,但它总是在更改为正确状态之前显示错误的状态。例如“显示全部”按钮将控制台记录“显示已完成”,然后如果您再次按下它,它将控制台记录“全部显示”

App.js

import React, { Component } from 'react';
import './App.css';
import TodoList from './components/TodoList.js'
import VisabilityFilter from './components/VisabilityFilter.js'

export const SHOW_ALL = 'show_all'
export const SHOW_COMPLETED = 'show_completed'

class App extends Component {
  constructor (props) {
    super(props)

    this.state = {
      inputValues: {
        'newTodo': ''
      },
      todos: [
        {
          task: 'My First Todo',
          completed: false
        }
      ],
      visabilityFilter: SHOW_ALL
    }

    this.addTodo = this.addTodo.bind(this)
    this.handleInputChange = this.handleInputChange.bind(this)
    this.handleKeyUp = this.handleKeyUp.bind(this)
    this.toggleCompleted = this.toggleCompleted.bind(this)
    this.removeTodo = this.removeTodo.bind(this)
    this.checkCompleted = this.checkCompleted.bind(this)
    this.setVisabilityFilter = this.setVisabilityFilter.bind(this)

  }

  handleInputChange (e) {
      const { inputValues } = this.state
      const { id, value } = e.target
      this.setState({
        inputValues: {
          ...inputValues,
          [id]: value
        }
      })
  }

  handleKeyUp (e) {
    var code = e.key
        if(code === 'Enter') {
          this.addTodo(e);
        }
  }

  toggleCompleted (e, index) {
    const { todos } = this.state

    todos[index].completed = !todos[index].completed

    todos.sort((a, b) => b.completed - a.completed)

    this.setState({ todos })
  }

  removeTodo (e, index) {
    const { todos } = this.state
    this.setState ({ todos: todos.filter((todo, i) => i !== index) })
  }

  addTodo (e) {
      const { todos, inputValues } = this.state
      const { dataset } = e.target

      if (inputValues[dataset.for] === '') return

      const newTodo = { task: inputValues[dataset.for], completed: false }
      todos.push(newTodo)

      this.setState({
        todos,
        inputValues: { ...inputValues, [dataset.for]: '' }
      })
  }

  checkCompleted (e, index) {
    const { todos } = this.state
    return { todos } && todos[index].completed
  }

  setVisabilityFilter (e) {
    const { visabilityFilter } = this.state
    const { dataset } = e.target

    this.setState({
      visabilityFilter: dataset.for
    })

    console.log ({ visabilityFilter })
  }

  render() {
    const { todos, inputValues, visabilityFilter } = this.state
    return (
      <div className="App">
        <TodoList
          todos={todos}
          inputValues={inputValues}
          addTodo={this.addTodo}
          handleInputChange={this.handleInputChange}
          removeTodo={this.removeTodo}
          toggleCompleted={this.toggleCompleted}
          handleKeyUp={this.handleKeyUp}
          checkCompleted={this.checkCompleted}
        />
        <VisabilityFilter setVisabilityFilter={this.setVisabilityFilter} />
      </div>
    );
  }
}

export default App;

VisabilityFilter.js

import React from 'react'
import { func } from 'prop-types'

import { SHOW_ALL, SHOW_COMPLETED } from '../App'

const VisabilityFilter = props => {
  return (
    <div>
      <button data-for={SHOW_COMPLETED} onClick={ props.setVisabilityFilter } >
        Show Completed Tasks
      </button>
      <button data-for={SHOW_ALL} onClick={ props.setVisabilityFilter }>
        Show All Tasks
      </button>
    </div>
  )
}

VisabilityFilter.propTypes = {
  setVisabilityFilter: func.isRequired
}

export default VisabilityFilter

【问题讨论】:

  • console.log 没有显示新状态的原因是setState() 是异步的。我在您的代码中找不到任何问题
  • 将你的 console.log 移动到作为 setState() 的第二个参数传递的函数中,就像这样 this.setState({ visabilityFilter: dataset.for }, ()=&gt;{console.log(this.state.visabilityFilter)} )

标签: javascript reactjs


【解决方案1】:

setState() 是异步的 (React docs),因此不会立即应用状态更改。如果你想注销新状态,setState() 接受一个函数作为第二个参数,并在状态更新时执行该函数。所以:

this.setState({ 
    abc: xyz 
  }, 
  () => console.log(this.state.abc),
)

或者也可以使用componentDidUpdate(),推荐

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-18
    • 1970-01-01
    • 2019-05-31
    • 2021-01-28
    相关资源
    最近更新 更多