Крючки реакции: Не удается получить доступ к обновленной переменной useState за пределами useEffect?

#javascript #reactjs #react-hooks

Вопрос:

Я новичок в react и создаю приложение react , в этом приложении продукты питания можно перетаскивать в список заказов с помощью react dnd , проблема , с которой я сталкиваюсь, заключается в том, что я не могу получить обновленную переменную списка заказов ни в одной функции за пределами эффекта использования,

в списке addFoodToOrderList , useEffect ,я печатаю ту же переменную списка заказов , но в списке addFoodToOrderList вывод пуст , я знаю, что useState является асинхронной функцией, но при добавлении 3-го элемента в список заказов он должен показывать по крайней мере первые 2 элемента, но в качестве вывода он выдает пустой массив(0), регистр для useEffect отличается

код :

 export default function FoodCardContainer() {
    const [liked,setLiked] = useState("")
    
    function handleLike(e) {
        setLiked(prevNotes => {
            return [...prevNotes,e];
          });
      }
    const [orderList, setOrderList] = useState([]);
      
    const [{ isOver }, drop] = useDrop(() => ({
        accept: "div",
        drop: (item) => {
         addFoodToOrderList(item.id)},
        collect: (monitor) => ({
          isOver: !!monitor.isOver(),
        }),
      }));
    
    const addFoodToOrderList = (id) => {
       const orderItem = fooditems.filter((f) => id === f._id)
       setOrderList((preorderLists) => {return [...preorderLists,orderItem[0]]});
       console.log("this one outside useEffect",orderList)
      };
   
   useEffect(() => {
     console.log("this one inside useEffect",orderList)
    },[orderList])
 

моя консоль:

введите описание изображения здесь

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

1. Я подозреваю useDrop , что он запоминает функцию, которую он выполняет, как закрытие с переменной addFoodToOrderList and initial orderList . Всякий FoodCard раз, когда выполняется повторная отрисовка, переданная функция useDrop может быть проигнорирована и по-прежнему удерживаться при первом вызове при начальной отрисовке.

Ответ №1:

Похоже, что переданная функция drop была сохранена в памяти и никогда не обновлялась. В документах это упоминается в качестве параметров для useDrop :

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

Поскольку вы предоставили спецификацию функции, по умолчанию она была пуста как массив в качестве deps.

Поэтому вы должны указать deps.

 const [{
    isOver
}, drop] = useDrop(() => ({
    accept: "div",
    drop: (item) => {
        addFoodToOrderList(item.id)
    },
    collect: (monitor) => ({
        isOver: !!monitor.isOver(),
    }),
}), [addFoodToOrderList]);
 

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

1. Хорошая находка, возможно, включает фрагмент кода, показывающий, как ее решить? Мне немного странно, что этот крючок по умолчанию использует пустой массив вместо того, чтобы не определять массив зависимостей и повторно фиксировать закрытие при каждом рендеринге. По умолчанию это может быть менее эффективным, но приведет к меньшей путанице в запоминании, как в этом вопросе.

2. @MarcBaumbach может быть да. Я добавил пример. Они говорят: «Значение по умолчанию-пустой массив для спецификации функции и массив, содержащий спецификацию для спецификации объекта».