React 子组件不会在其状态更改时重新渲染

Posted

技术标签:

【中文标题】React 子组件不会在其状态更改时重新渲染【英文标题】:React child component do not re-render on it state change 【发布时间】:2017-10-04 20:56:55 【问题描述】:

我有一个返回其他组件的任务组件。但是,当我从 Tasks 组件更改子组件之一的状态时,它不会重新渲染。

我将 'newTaskAdded' 状态从父级传递给子级作为道具并将其分配给子级以重新渲染子组件,但它仍然没有发生。

我的目标是: 当用户添加任务时,我希望它立即显示在屏幕上,这意味着用户必须刷新页面才能看到新任务。

Tasks.jsx:

import React ,  Component  from 'react'
import axios from 'axios'
import Name from './Name.jsx'
import ShowTasks from './ShowTasks.jsx'

class Tasks extends Component 
  constructor(props) 
    super(props)
    this.state=
      task: '',
      newTaskAdded:false,
      newTask:[],
    
    this.handleChange = this.handleChange.bind(this)
    this.addTask = this.addTask.bind(this)
  
  handleChange(event) 
    this.setState(task: event.target.value)
  
  addTask() 
    axios.post('/api/addtask',
      name:this.props.name,
      task:this.state.task
    )
    .then((res) => 
      if(res.status=='200')
        this.setState (task:'')
        this.setState (newTaskAdded:true)
        this.setState (newTask: res.data.message[res.data.message.length-1] )
      
    )
    .catch((err) => 
      if(err) throw err
    )
  

  render() 
    return (
      <div>
        <div>
          <Name name=this.props.name />
        </div>
        <div>
          <input value=this.state.task onChange=this.handleChange type="text" name="task" />
          <button type="button" onClick=this.addTask>Add Task</button>
        </div>
        <ShowTasks name=this.props.name updated=this.state.newTaskAdded />
      </div>
    )
  


export default Tasks

ShowTasks.jsx

import React ,  Component  from 'react'
import axios from 'axios'
import Completed from './Completed.jsx'
import NotCompleted from './NotCompleted.jsx'

class ShowTasks extends Component 
  constructor(props) 
    super(props)
    this.state = 
      tasks:[],
      updated:this.props.updated
    
  
  componentWillMount()
    axios.post('/api/loadtasks', 
      name: this.props.name
    )
    .then((res) => 
      console.log('res', res);
      this.setState (tasks:res.data.tasks)
    )
    .catch((err) => 
      throw err
    )
  
  render() 
    return (
      <div className='pointer'>
        this.state.tasks.map((task) => 
          if(task.completed) 
            return <Completed key=task._id ...task />
          
          else 
            return <NotCompleted key=task._id ...task />
          
        )
      </div>
    )
  


export default ShowTasks

【问题讨论】:

您确定then 部分正在执行吗?你有控制台日志吗? 复制:***.com/a/41971336/3734057 感谢@Chris 的回复。它确实有效 【参考方案1】:

所以问题出在您将道具设置为状态的子函数中,

您在构造函数中将 props 设置为 state,并且不会在每次 props 更改时调用构造函数,而只会在组件第一次渲染时调用构造函数,因此不会使用正确的值更新状态。

您应该在 componentWillReceiveProps 函数中设置 props,该函数在父组件的每次渲染时调用

class ShowTasks extends Component 
  constructor(props) 
    super(props)
    this.state = 
      tasks:[],
      updated:this.props.updated
    
  
  componentWillReceiveProps(nextProps) 
      this.setState(updated: nextProps.updated);
  
  componentWillMount()
    axios.post('/api/loadtasks', 
      name: this.props.name
    )
    .then((res) => 
      console.log('res', res);
      this.setState (tasks:res.data.tasks)
    )
    .catch((err) => 
      throw err
    )
  
  render() 
    return (
      <div className='pointer'>
        this.state.tasks.map((task) => 
          if(task.completed) 
            return <Completed key=task._id ...task />
          
          else 
            return <NotCompleted key=task._id ...task />
          
        )
      </div>
    )
  


export default ShowTasks

详细了解生命周期函数以及何时使用它们here:

【讨论】:

您好,感谢您的快速回复。但它仍然无法正常工作。未访问 componentWillMount 函数。 componentWillMount 没有被访问是什么意思【参考方案2】:

好的!解决了:

Tasks.jsx:

import React ,  Component  from 'react'
import axios from 'axios'
import Name from './Name.jsx'
import ShowTasks from './ShowTasks.jsx'

class Tasks extends Component 
  constructor(props) 
    super(props)
    this.state=
      user:this.props.user,
      task:'',
      newTask:[],
    
    this.handleChange = this.handleChange.bind(this)
    this.addTask = this.addTask.bind(this)
  

  handleChange(event) 
    this.setState(task: event.target.value)
  

  addTask() 
    axios.post('/api/addtask',
      name:this.state.user.name,
      task:this.state.task
    )
    .then((res) => 
      if(res.status=='200')
        this.setState (user:this.state.user)
        this.setState (newTask: res.data.message[res.data.message.length-1] )
      
    )
    .catch((err) => 
      if(err) throw err
    )
  

  render() 
    return (
      <div>
        <div>
          <Name name=this.props.user.name />
        </div>
        <div>
          <input value=this.state.task onChange=this.handleChange type="text" name="task" />
          <button type="button" onClick=this.addTask>Add Task</button>
        </div>
        <ShowTasks user=this.state.user/>
      </div>
    )
  


export default Tasks

ShowTasks.jsx:

import React ,  Component  from 'react'
import axios from 'axios'
import Completed from './Completed.jsx'
import NotCompleted from './NotCompleted.jsx'

class ShowTasks extends Component 
  constructor(props) 
    super(props)
    this.state = 
      user: this.props.user,
      tasks:[],
    
    this.loadTasks=this.loadTasks.bind(this)
  

  loadTasks() 
    axios.post('/api/loadtasks', 
      name: this.state.user.name
    )
    .then((res) => 
      this.setState (tasks:res.data.tasks)
    )
    .catch((err) => 
      throw err
    )
  

  componentWillReceiveProps(nextProps) 
    this.loadTasks()
  

  render() 
    return (
      <div className='pointer'>
        this.state.tasks.map((task) => 
          if(task.completed) 
            return <Completed key=task._id ...task />
          
          else 
            return <NotCompleted key=task._id ...task />
          
        )
      </div>
    )
  


export default ShowTasks

【讨论】:

以上是关于React 子组件不会在其状态更改时重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

state 用作组件中的 props,状态更改不会重新渲染组件

状态更改时不会重新渲染 React-typing-animation

有没有办法让上下文仅在其数据更改时重新渲染?

React Native 和 Redux:为啥子组件不会在每次状态更新时重新渲染?

即使在调用 setState 之后,React.js 子状态也不会重新渲染?

React 功能组件中状态更改后组件未重新渲染