Реагировать: массив useState не изменяется при вызове метода изменения состояния

#javascript #reactjs #next.js

Вопрос:

Состояние массива не изменяется при вызове метода изменения состояния :

 const [arrayOfDocuments, setArrayOfDocuments] = useState([]);
 

я пытался : setArrayOfDocuments(...[]); or setArrayOfDocuments([]);

где я использую свой метод :

   const pushToArrayOfDocuments = (obj) => {
    const arr = arrayOfDocuments;
    if (obj.filename amp;amp; obj.file amp;amp; obj.expiredate amp;amp; obj.doctype) {
      const index = arr.map((e) => e.filename).indexOf(obj.filename);
      if (index !== -1) {
        arr[index] = obj;
      } else {
        arr.push(obj);
      }
      setArrayOfDocuments(arr);
    }
  };
 

Может быть, проблема в том, чтобы подтолкнуть? и я должен это сделать setArrayOfDocuments(...arr); or setArrayOfDocuments(prev => [...prev,...arr]) , но если я сделаю это, я думаю, что это будет продолжаться бесконечно, когда я перейду pushToArrayOfDocuments к подкомпонентам.
Подобный этому :

 OperatorDocument
                  key={`Durc${count}`}
                  title="Durc"
                  description="Descrizione Durc"
                  setDocument={pushToArrayOfDocuments}
                  document={getObjectByName('Durc')}
                  filedocname="Durc"
                />
 

Редактировать :
делаем вот так : setArrayOfDocuments([...arr]);
я получаю Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
Любая помощь будет признательна.

Комментарии:

1. arr будет по-прежнему равно arr , поэтому изменение состояния не будет вызвано. Ты мог бы просто сделать … > setArrayOfDocuments([...arr]);

2. @Keith таким образом, это приведет к бесконечному рендерингу любого решения ?

3. so i guess it will go in infinte rendering as i'm passing pushToArrayOfDocuments В этом -то и проблема. Почему эта измененная ссылка вызывает бесконечный рендеринг? Вот в чем заключается настоящая проблема — покажите useEffect OperatorDocument , что никогда не используйте push (или splice ) или что-либо, что изменяет что-либо в React.

4. Поместите старый массив в новую переменную, т. Е. updatedArray Добавьте в нее изменения , установите состояние для этого массива.

Ответ №1:

Во-первых, вы никогда не должны напрямую изменять useState состояние, использовать их как неизменяемые сущности. Если вы хотите использовать его в качестве начального значения, клонируйте его перед:

 const arr = [...arrayOfDocuments]
// or
const arr = arrayOfDocuments.slice()
 

Во-вторых, вы передаете один и тот же массив состояний сеттеру, тогда состояние не будет обновляться. Клонирование государства решит этот второй вопрос.

Наконец, лучший способ построить новое состояние из старого значения-это использовать функцию:

 setState(oldValue => (/* construct new state based on old value */))
 

это позволит избежать использования значения, которое не является актуальным.
В конце концов, у вас будет:

 const pushToArrayOfDocuments = (obj) => {
  if (obj.filename amp;amp; obj.file amp;amp; obj.expiredate amp;amp; obj.doctype) {
    setArrayOfDocuments(oldArr => {
        const arr = oldArr.slice();
        const index = arr.map((e) => e.filename).indexOf(obj.filename);

        if (index !== -1) {
          arr[index] = obj;
        } else {
          arr.push(obj);
        }

        return arr;
      }
    )
  }
};
 

Ответ №2:

Вам нужно клонировать свой массив, прежде чем добавлять его в состояние.

 const arr = arrayOfDocuments.slice();
 

Полный фрагмент:

 const pushToArrayOfDocuments = (obj) => {
  if (obj.filename amp;amp; obj.file amp;amp; obj.expiredate amp;amp; obj.doctype) {
    const arr = arrayOfDocuments.slice();
    const index = arr.findIndex(({ filename }) => filename === obj.filename);

    if (index > -1) {
      arr[index] = obj;
    } else {
      arr.push(obj);
    }

    setArrayOfDocuments(arr);
  }
};
 

Ответ №3:

Я добавляю аналогичную проблему, и я решил ее с помощью

вместо

const arr = Массив документов

попробуйте распространить исходный массив

const arr = […массив документов]