setState() 之后的 Console.log() 不返回更新的状态 [英] Console.log() after setState() doesn't return the updated state

查看:24
本文介绍了setState() 之后的 Console.log() 不返回更新的状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I've created a simple todo list to learn react and i'm trying to add some additional features. At the moment i'm trying to add buttons that toggle the list of items, so it either shows all the tasks or just those that are completed.

I've written a function to change the state of my visabilityFilter so I can later use this to toggle the items in the list, but it isn't behaving how it should be.

I console log the visabilityFilter variable but it always shows the wrong state before changing to the correct state. e.g. the 'show all' button will console log 'show completed' then if you press it again it will console log 'show all'

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

解决方案

setState() is async (React docs), so the state changes won't be applied immediately. If you want to log out the new state,setState() takes in a function as the second argument and performs that function when the state is updated. So:

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

Or you can also use componentDidUpdate(), which is recommended

这篇关于setState() 之后的 Console.log() 不返回更新的状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆