React Hooks и память MERN

Prodlem с React Hooks (стек MERN)

Внезапно после попытки добавить фильтр на страницу перестали показывать объекты (хотя они точно есть, даже новые создаются). За пару дней моих стараний ничего не получилось (даже пытался откатить код на старую версию, все равно не работает).

Домашний файл:

import React, { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { axiosInstance } from '../helpers/axiosInstance';
import { HideLoading, ShowLoading } from '../redux/alertsSlice';
import { Col, Row, message } from 'antd';
import Bus from '../components/Bus';

function Home() {
  const { user } = useSelector(state => state.users)
  const [filters = {}, setFilters] = useState({});
  const dispatch = useDispatch();
  const [buses, setBuses] = useState([]);

  const getBuses = async () => {
    const tempFilters = {};
    Object.keys(filters).forEach((key) => {
      if (filters[key]) {
        tempFilters[key] = filters[key];
      }
    })
    try {
      dispatch(ShowLoading())
      const response = await axiosInstance.post(
        "/api/buses/get-all-buses",
        tempFilters
      );
      dispatch(HideLoading());
      if (response.data.success) {
        setBuses(response.data.data);
      } else {
        message.error(response.data.message);
      }
    } catch (error) {
      dispatch(HideLoading());
      message.error(error.message);
    }
  }
  useEffect(() => {
    getBuses();
    //setSelectedBus();
  }, [])
  return (
    <div>
      <div className='my-3 card p-2'>
        <Row gutter = {10}>
          <Col lg = {6} sm = {24}>
            <input type='text'
              placeholder='From'
              value = {filters.from}
              onChange = {(e) => setFilters({ ...filters, from: e.target.value })}
            />
          </Col>
          <Col lg = {6} sm = {24}>
            <input type='text'
              placeholder='To'
              value = {filters.to}
              onChange = {(e) => setFilters({ ...filters, to: e.target.value })}
            />
          </Col>
          <Col lg = {6} sm = {24}>
            <input type='date'
              placeholder='Date'
              value = {filters.journeyDate}
              onChange = {(e) => setFilters({ ...filters, journeyDate: e.target.value })}
            />
          </Col>
          <Col lg = {6} sm = {24}>
            <button className='primary-btn' onClick = {() => getBuses()}>
              Filter
            </button>
          </Col>
        </Row>
      </div>
      <div>
        <Row gutter = {[15, 15]}>
          {buses.filter((bus) => bus.status === "Yet to start").map((bus) => (
            <Col lg = {12} xs = {24} sm = {24}>
              <Bus bus = {bus} />
            </Col>
          ))}
        </Row>
      </div>
    </div>
  )
}

export default Home

Файл busRoute (там больше всего интересует get-all-buses):

const router = require('express').Router();
const Bus = require("../models/busModel")
const authMiddleware = require("../middlewares/authMiddleware")


// add-bus

router.post('/add-bus', async (req, res) => {
    try {
        const existingBus = await Bus.findOne({ number: req.body.number })

        if (existingBus) {
            return res.status(200).send({
                seccess: false,
                meggage: 'Bus already exists',
            })
        }
        const newBus = new Bus(req.body);
        await newBus.save();
        return res.status(200).send({
            success: true,
            message: 'Bus added successfully'
        })
    } catch (error) {
        res.status(500).send({
            success: false,
            meggage: error.message
        })
    }
});

// update-bus

router.post("/update-bus", authMiddleware, async (req, res) => {
    try {
        await Bus.findByIdAndUpdate(req.body._id, req.body)
        return res.status(200).send({
            success: true,
            message: 'Bus updated successfully',
        })
    }
    catch (error) {
        res.status(500).send({success: false, message: error.meggage})
    }
});

// delete-bus

router.post("/delete-bus", authMiddleware, async (req, res) => {
    try {
        await Bus.findByIdAndDelete(req.body._id, req.body)
        return res.status(200).send({
            success: true,
            message: 'Bus deleted    successfully',
        })
    }
    catch (error) {
        res.status(500).send({success: false, message: error.meggage})
    }
});


// get-all-buses

router.post("/get-all-buses", authMiddleware, async (req, res) => {
    try {
        const buses = await Bus.find();
        return res.status(200).send({
            success: true,
            message: "Buses fetched successfully",
            data: buses,
        })
    } catch (error) {
        res.status(500).send({
            success: false,
            message: error.message
        })
    };
})


//get-bus-by-id

router.post("/get-bus-by-id", authMiddleware, async (req, res) => {
    try {
        const bus = await Bus.findById(req.body._id);
        return res.status(200).send({
            success: true,
            message: "Buses fetched successfully",
            data: bus,
        })
    } catch (error) {
        res.status(500).send({
            success: false,
            message: error.message
        })
    };
})




module.exports = router;

p.s. Позже я понял, что данные шины просто не передаются, и консоль выдала ошибку для первого прикрепленного файла: "Строка 41:6: React Hook useEffect имеет недостающую зависимость: 'getBuses'. Либо включите ее, либо удалите зависимость массив реагирующих хуков/исчерпывающих отложений ":(

https://i.stack.imgur.com/qUxvA.png

Я использую MobgoDB:

const mongoose = require('mongoose');

const busSchema = new mongoose.Schema ({
    name : {
        type: String,
        require: true
    },
    number : {
        type: String,
        require: true
    },
    capacity : {
        type: Number,
        require: true
    },
    from : {
        type: String,
        require: true
    },
    to : {
        type: String,
        require: true
    },
    journeyDate : {
        type: String,
        require: true
    },
    departure : {
        type: String,
        require: true
    },
    arrival : {
        type: String,
        require: true
    },
    type : {
        type: String,
        require: true
    },
    fare : {
        type: Number,
        require: true
    },
    seatsBooked : {
        type: Array,
        default:[]
    },
    status: {
        type: String,
        default: 'Yet to Start',
    }
})

module.exports = mongoose.model('buses', busSchema)

Мы не можем видеть данные, которые находятся в состоянии, но фильтрует ли filter((bus) => bus.status === "Yet to start") все результаты? Что конкретно не работает? Похоже, конечная точка возвращает пустой массив. Вы исследовали свой бэкенд? Пожалуйста, отредактируйте, чтобы предоставить более подробную информацию о проблеме.

Drew Reese 23.05.2023 17:32
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как бы то ни было, ваш метод getBuses вызывается только один раз, когда компонент монтируется. Ваша консоль просит вас добавить свою ссылку в массив зависимостей, чтобы ее можно было повторно запускать каждый раз при обновлении getBuses. Попробуйте заменить useEffect на следующее:

useEffect(() => {
    getBuses();
}, [getBuses]) // <-- This is the dependency array, filled with `getBuses`

По тем же причинам вы также можете захотеть обернуть свой метод getBuses в useCallback, что позволит лучше обрабатывать изменения его зависимостей (таких как filters, например).


РЕДАКТИРОВАТЬ 1:

Следующий фрагмент, который вы поместили в свой код

const tempFilters = {};
Object.keys(filters).forEach((key) => {
  if (filters[key]) {
    tempFilters[key] = filters[key];
  }
})

в основном копирует каждый ключ (и связанное с ним значение) из вашего объекта filters в новый объект без применения какой-либо обработки. Поэтому вы можете избавиться от него и напрямую ссылаться на объект filters.

Еще одним улучшением было бы обернуть ваш метод getBuses в useCallback с зависимостью от filters, что гарантирует, что он всегда использует актуальные данные об этом состоянии filters при вызове вашего API.

Кроме того, вы можете обновить вызов try-catch с помощью простых методов Promises Prototype, чтобы сделать поток более читабельным (это просто предпочтение и зависит от вашего стиля кодирования).

Вот пример обновленного метода getBuses:

const getBuses = useCallback(async () => {
  dispatch(ShowLoading());
  axiosInstance.post("/api/buses/get-all-buses", tempFilters)
    .then((response) => {
      if (response?.data?.success) {
        setBuses(response.data.data);
      } else {
        message.error(response.data.message);
      }
    })
    .catch((error) => message.error(error.message))
    .finally(() => dispatch(HideLoading()));
  }, [filters]);

Еще одним улучшением будет создание динамического метода обработчика onChange для ваших входных данных. Например, вы можете сделать следующее:

const handleOnChange = useCallback(({ target: { name, value } }) => {
  setFilters((prevState) => ({ ...prevState, [name]: value }));
}, []);

и добавьте атрибут name к каждому входу, таким образом вам просто нужно будет передать его handleOnChange в качестве значения реквизитам onChange. Вот пример обновленного ввода:

<input type='text'
  placeholder='From'
  value = {filters.from}
  name = "from"
  onChange = {handleOnChange}
/>

О, спасибо большое, мне помогло. Да, я хотел бы узнать больше о том, о чем вы говорите.

Вишневский Владислав 23.05.2023 18:41

Я переделал функцию getBuses с помощью useCallback, но фильтры все равно не работают :(( ``` const getBuses = useCallback(async() => { const tempFilters = {}; Object.keys(filters).forEach((key ) => { if (filters[key]) { tempFilters[key] = filter[key]; } }); ..... ```

Вишневский Владислав 23.05.2023 18:45

Рад, что смог быть полезен! Я отредактировал свой ответ, чтобы дать дополнительную информацию. Дайте мне знать, если вам нужна помощь в понимании этого :)

Tam 23.05.2023 22:09

о, спасибо большое, но все равно не работает. Вот что у меня на данный момент: В get-all-buses если я напишу const buses = await Bus.find(req.body); автобусы не будут отображаться на главной странице, но если я напишу req.body._id или req .body.buses или req.body.filters то все будет работать нормально. Также я написал console.info(req.body.filters) перед этой строчной буквой, и она продолжает показывать «undefined». Я пробовал это в версии всего и вашего кода. О, я ненавижу этот проект...

Вишневский Владислав 25.05.2023 16:17

О, у меня может быть идея, почему у вас возникла такая проблема. Не могли бы вы обновить свой пост, чтобы предоставить содержимое вашего файла busModel и уведомить меня, когда вы это сделаете? (Я подозреваю, что вы используете ORM с определенной структурой параметров в своих методах, которую вы не соблюдаете, что может привести к такого рода проблемам)

Tam 26.05.2023 12:34

Я использую МонгоДБ. Я обновил пост и добавил необходимую информацию

Вишневский Владислав 28.05.2023 16:42

Если вам нужно что-то еще, я могу добавить новую информацию

Вишневский Владислав 31.05.2023 13:52

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

Tam 01.06.2023 11:21

Другие вопросы по теме