useState на React Hooks не обновляет массив - PullRequest
0 голосов
/ 19 февраля 2020

Я перепробовал много вещей и не могу понять, почему setTypes не будет обновлять массив 'types' ??

import { useState, useEffect } from 'react';
import { PostList } from './post-list';
import * as api from '../utils/api';

export const PostSelector = (props) => {
  const [posts, setPosts]     = useState([]);
  const [loading, setLoading] = useState(false);
  const [type, setType]       = useState('post');
  const [types, setTypes]     = useState({});

  const fetchTypes = async () => {
    setLoading(true);
    const response = await api.getPostTypes();
    delete response.data.attachment;
    delete response.data.wp_block;
    const postTypes = response.data;
    console.log(response.data); // {post: {…}, page: {…}, case: {…}}
    setTypes(postTypes);
    console.log(types); // []

    // Why types remain empty??
  }

const loadPosts = async (args = {}) => {
  const defaultArgs = { per_page: 10, type };
  const requestArgs = { ...defaultArgs, ...args };


  requestArgs.restBase = types[requestArgs.type].rest_base; // Cannot read property 'rest_base' of undefined

  const response = await api.getPosts(requestArgs);
  console.log(response.data);
}

useEffect(() => {
  fetchTypes();
  loadPosts();
}, []);

  return (
    <div className="filter">
      <label htmlFor="options">Post Type: </label>
      <select name="options" id="options">
        { types.length < 1 ? (<option value="">loading</option>) : Object.keys(types).map((key, index) => <option key={ index } value={ key }>{ types[key].name }</option> ) }
      </select>
    </div>
  );
}

Пожалуйста, посмотрите на console.log и обратите внимание на разные ответы.

Я пытаюсь загрузить список типов, в данном случае «post», «page» и «case», а затем отобразить список сообщений на основе текущего «type» , Тип по умолчанию 'post'.

Если я добавлю [types] для использованияEffect. Я, наконец, получаю значения, но компонент отображается без остановки.

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

Как мы можем решить эту проблему тогда? Независимо от причин, как мы можем это сделать? Как мы работаем с нашим состоянием в любой момент времени и выполняем вычисления на основе нашего состояния, если мы не знаем, когда оно станет доступным? Как мы можем быть уверены, что подождем, что нам нужно, а затем используем ожидаемые значения?

Ответы [ 3 ]

0 голосов
/ 19 февраля 2020
SetTypes

useState является асинхронной функцией, поэтому изменения вступают в силу не сразу. Вы можете использовать useEffect, чтобы проверить, что что-то меняется

useEffect(()=>{
    const defaultArgs = { per_page: 10, type };
    const requestArgs = { ...defaultArgs, ...args };
    requestArgs.restBase = types;
    console.log("types updated",types)
},[types])

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

0 голосов
/ 19 февраля 2020

Вы объявили, что ваши типы являются массивом, но вы передаете в него словарь словарей. Попробуйте это:

const [types, setTypes]     = useState({});

Вам также не нужно вызывать

loadPosts()

, потому что ловушка useState повторно отрендерит ваш компонент, обновив только то, что нужно.

0 голосов
/ 19 февраля 2020

Кажется, что useState является асинхронным и не обновляет значение сразу после его вызова.

Просмотрите этот же случай здесь

...