UseState не повторный рендеринг при обновлении вложенного объекта - PullRequest
1 голос
/ 08 мая 2019

Я обновляю в useEffect, помещая данные в старый объект состояния и возвращая их в качестве значения.

Этот код фактически меняет переменную _series с useState (), но повторного рендеринга не происходитпочему?

import { TimeSeries, Pipeline, Stream, EventOut, TimeEvent, TimeRange  } from "pondjs";

export default () => {

  const [_series, $series] = useState(()=>{
    let state = { data : { "name": "x", "columns": ["time", "value"], "points": [], "i" : 0}}
    for(let i=10; i >= 0; i--){state.data.points.push( [new Date(i)-(i*100), Math.round(Math.random()*100)])}
    return state;
  })

  useEffect(() => {
    const interval = setInterval(() => {
      $series(s => {
        s.data.points.push( [new Date(s.data.i*1000), Math.round(Math.sin(s.data.i/10)*50+50)] )
        s.data.points.shift();
        s.data.i++;
        return s;
      });
    }, 500);
  }, []);


    return(
    <p>{

          JSON.stringify((new TimeSeries(_series.data)).collection())

    }</p>
    )

}


Возможно, я также допустил ошибку, обновив ключ "i" внутри состояния, поэтому я пытаюсь обновить несколько частей объекта одновременно.Это плохая практика?

1 Ответ

1 голос
/ 08 мая 2019

Проблема в том, что когда вы изменяете состояние путем изменения исходного состояния, его значение обновляется при исходной ссылке и, следовательно, реагирует, думает, что ничего не изменилось, и, следовательно, оно не перерисовывается, поэтому ожидается, что обработка состояние, как будто оно является неизменным при попытке обновить состояние

 const { useState, useEffect } = React;
 const App = () => {
    
      const [_series, $series] = useState(()=>{
        let state = { data : { "name": "x", "columns": ["time", "value"], "points": [], "i" : 0}}
        for(let i=10; i >= 0; i--){state.data.points.push( [new Date(i)-(i*100), Math.round(Math.random()*100)])}
        return state;
      })
    
      useEffect(() => {
        const interval = setInterval(() => {
          $series(s => {
            return {
                ...s,
                data: {
                  ...s.data,
                  i: s.data.i + 1,
                  points: [...s.data.points.slice(1), [new Date(s.data.i*1000), Math.round(Math.sin(s.data.i/10)*50+50)]]
                }
            }
          });
        }, 500);
      }, []);
    
    
        return(
        <p>{
    
              JSON.stringify(_series.data)
    
        }</p>
        )
    
    }
    
ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app" />
...