setState()之后的Console.log()不返回更新状态

时间:2019-02-15 16:35:50

标签: javascript reactjs

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

我编写了一个函数来更改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

2 个答案:

答案 0 :(得分:2)

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

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

或者您也可以使用componentDidUpdate(),建议使用

答案 1 :(得分:0)

如果您想在setstate之后记录更新后的状态,我们可以在setTimeout中控制状态。请参考以下代码。

setTimeout(function(){
    console.log(this.state.value); 
},1000);

上面的代码具有1秒的超时时间。我们可以减少超时。