【问题标题】:Update parent state from child component and re-render this child when parent state is update从子组件更新父状态并在父状态更新时重新渲染该子组件
【发布时间】:2021-04-06 02:06:36
【问题描述】:

我正在学习 React,我整天都在尝试解决我的问题,但没有成功。然后决定在这里提出我的第一个问题。

我有子组件,包括 React-Datepicker 组件和单独的“第二天”和“前一天”按钮来更改所选日期。

SelectedDate 存储在父组件的状态中。

我正在尝试从子组件更新父组件的状态,然后当状态更新时,子组件应重新渲染,因为此状态作为道具传递给同一个子组件。

我已设法从子组件更改父状态,但子组件未重新渲染,因此 Datepicker 日期未更新。

我应该如何解决这个问题?

下面是我没有导入行的代码。

// App.js

function App() {
  const [selectedDate, setSelectedDate] = useState(new Date())

  const incrementDate = () => {
    let next = selectedDate
    next.setDate(next.getDate() + 1)

    setSelectedDate(next)
  }

  const decrementDate = () => {
    let previous = selectedDate
    previous.setDate(previous.getDate() - 1)

    setSelectedDate(previous)
  }

  return (
    <div className="App">
      <Child 
        selectedDate={selectedDate}
        setSelectedDate={setSelectedDate}
        decrementDate={decrementDate}
        incrementDate={incrementDate} />
    </div>
  )
}

// Child.js

const Child = ({ selectedDate, setSelectedDate, decrementDate, incrementDate }) => {
  return (
    <div className='datepicker-wrapper'>
      <ArrowLeft className='date-arrow' onClick={decrementDate} />
        <DatePicker
          selected={selectedDate}
          onChange={(date) => setSelectedDate(date)}
        />
      <ArrowRight className='date-arrow' onClick={incrementDate} />
    </div>
  )
}

解决方案:

增量和减量函数的变化:

let next = new Date(selectedDate.valueOf())
let previous = new Date(selectedDate.valueOf())

【问题讨论】:

  • 如果您要更新状态并根据更新后的值渲染组件,为什么不在子组件中也这样做呢?为什么你需要 parent state 和 setter 来解决这个问题?
  • 是你的递减和递增按钮没有按预期工作吗?可能是因为您在 incrementDatedecrementDate 函数中更改了 Date 对象。试试let previous = new Date(selectedDate.valueOf())
  • 它应该可以工作,如果道具改变了子组件应该重新渲染。你确定 DatePicker 道具是正确的吗?你应该使用value 而不是selected
  • @HåkenLid 成功了!谢谢!即使我在控制台中记录了递增和递减函数中的日期值,我也没有想到这一点。

标签: javascript reactjs


【解决方案1】:

当你用 React 更新状态时,你应该总是创建新的状态对象,而不是仅仅改变现有的状态。

  const incrementDate = () => {
    let next = new Date(selectedDate.valueOf())
    next.setDate(next.getDate() + 1)
    setSelectedDate(next)
  }

  const decrementDate = () => {
    let previous = new Date(selectedDate.valueOf())
    previous.setDate(previous.getDate() - 1)
    setSelectedDate(previous)
  }

React 有各种优化,因此子组件只有在状态发生变化时才会重新呈现。许多 javascript 方法,例如 Date.setDate() 会在原地改变原始对象。简单地用 let previous = selectedDate 分配一个新名称不会创建一个新的 Date 对象。要创建新日期,您必须在更新程序函数的某处使用new Date()

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,用一个额外的函数来计算它的值 从孩子开始,然后用它更新状态,而且很容易用 console.log 跟踪它。 您可以将其视为中间件。 试试看:

    function App() {
      const [selectedDate, setSelectedDate] = useState(new Date())
    
      const incrementDate = () => {
        let next = selectedDate
        next.setDate(next.getDate() + 1)
    
        setSelectedDate(next)
      }
      const onDateChane = (date) => {
        console.log(date)
        setSelectedDate(date)
        }
        
      const decrementDate = () => {
        let previous = selectedDate
        previous.setDate(previous.getDate() - 1)
    
        setSelectedDate(previous)
      }
    
      return (
        <div className="App">
          <Child 
            selectedDate={selectedDate}
            setSelectedDate={setSelectedDate}
            decrementDate={decrementDate}
            incrementDate={incrementDate} />
        </div>
      )
    }

    【讨论】:

      【解决方案3】:

      子组件没有渲染,因为你忘记添加 useEffect 钩子了。

       import React,{useEffect} from 'react'
      
          const Child = ({ selectedDate, setSelectedDate, decrementDate, incrementDate }) => {
           useEffect(()=>{},[selectedDate]);
            return (
              <div className='datepicker-wrapper'>
                <ArrowLeft className='date-arrow' onClick={decrementDate} />
                  <DatePicker
                    selected={selectedDate}
                    onChange={(date) => setSelectedDate(date)}
                  />
                <ArrowRight className='date-arrow' onClick={incrementDate} />
              </div>
            )
          }
      

      【讨论】:

        猜你喜欢
        • 2022-06-29
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        • 2021-03-02
        • 1970-01-01
        • 2021-01-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多