UseEffect React-native Ошибка или логическая ошибка? - PullRequest
1 голос
/ 10 июля 2020

У меня есть этот компонент секундомера, который имеет проводное поведение: секундомер работает отлично, за исключением того, что он прекращает повторный рендеринг в пользовательском интерфейсе, когда я комментирую строку setTest(val => val + 1) изнутри useEffect (). Я подтвердил, что timeArray по-прежнему обновляется с помощью console.log, а <Text> в пользовательском интерфейсе - нет. Пожалуйста, помогите, если вы заметили что-то логически неправильное с кодом ниже:

const Stopwatch = () => {
    const [timeArray, setTime] = useState([0,0,0])
    const [test, setTest] = useState(0)

    useEffect(() => {
        const interval = setInterval(() => {
            setTime(val => time(val))    
            setTest(val => val + 1)  <-- commenting this line breaks UI re-rendering below of var timeArray!!
          }, 1000)
          return () => clearInterval(interval)
        },[])

    return(
        <View>
             <Text>{timeArray[2]}:{timeArray[1]}:{timeArray[0]}</Text> 
        </View>
    )
}

const time = (value) =>{
    value[0]++
    if (value[0] == 59){
        value[1]++
        value[0] = 0   
    }
    if (value[1] == 59 && value[0] == 59){
        value[2]++
        value[0] = 0
        value[1] = 0    
    }
    return value
}
 
export default Stopwatch

Ответы [ 2 ]

1 голос
/ 10 июля 2020

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

  useEffect(() => {
    const interval = setInterval(() => {
      const t = time(timeArray);
      setTime([...t]);// creating new array and setting to the state
      // setTime(t);// assigning the same array. rerender won't happen
    }, 1000);
    return () => clearInterval(interval);
  }, []);
1 голос
/ 10 июля 2020

Значение, возвращаемое функцией времени, устанавливает новое состояние для setTime. Итак, чтобы выполнить обновление состояния, вы должны распределить значения в состояние setTime.

Ссылка на CodeSandBox Здесь

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function App() {
  const [timeArray, setTime] = useState([0, 0, 0]);
  const [test, setTest] = useState(0);

  const time = value => {
    value[0]++;
    if (value[0] === 59) {
      value[1]++;
      value[0] = 0;
    }
    if (value[1] === 59 && value[0] === 59) {
      value[2]++;
      value[0] = 0;
      value[1] = 0;
    }
    return value;
  };

  useEffect(() => {
    const interval = setInterval(() => {
      const data = time(timeArray);
      setTime([...data]);
      //setTest(val => val + 1)
    }, 1000);
    return () => clearInterval(interval);
  }, [timeArray]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <div>
        <p>
          {timeArray[2]}:{timeArray[1]}:{timeArray[0]}
        </p>
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
    <div id="root"></div>
...