Мое состояние не обновляется с помощью React Hooks - PullRequest
2 голосов
/ 05 августа 2020

У меня есть событие, которое запускается при изменении. Это событие проверяет, какой фильтр был изменен, а затем обновляет состояние соответственно.

Если бы я не использовал перехватчики реакции, я бы выбрал что-то вроде этого -

const target = e.target;
const value = e.type === "checkbox" ? target.checked : target.value;
const name = e.target.name;    
this.setState({ [name]: value });

Как вы см. Я мог бы обновить имя состояния, используя [name], но поскольку я использую перехватчики реакции, я не могу использовать вышеуказанное. Вместо этого я получил это -

  const [type, setType] = useState("all");
  const [capacity, setCapacity] = useState(1);
  const [price, setPrice] = useState(0);
  const [minPrice, setMinPrice] = useState(0);
  const [maxPrice, setMaxPrice] = useState(0);
  const [minSize, setMinSize] = useState(0);
  const [maxSize, setMaxSize] = useState(0);

  const handleChange = (e) => {
    const target = e.target;
    const value = e.type === "checkbox" ? target.checked : target.value;
    const name = e.target.name;
    
    switch (name) {
      case "type":
        setType(value);
        break;
      case "capacity":
        setCapacity(value);
        break;
      case "price":
        setPrice(value);
        break;
      case "minPrice":
        setMinPrice(value);
        break;
      case "maxPrice":
        setMaxPrice(value);
        break;
      case "minSize":
        setMinSize(value);
        break;
      case "maxSize":
        setMaxSize(value);
        break;
      default:
        return;
    }
  };

То, что вы видели выше, по какой-то причине не работает. Когда я запускаю фильтр, он попадает в корпус, поскольку я уже это тестировал, но состояние, похоже, не обновляется. Имя и значение также были зарегистрированы, и они тоже в порядке. Я не уверен, что вызывает это, и я только новичок в программировании, поэтому любая помощь будет оценена!

*** Просто, чтобы повторить, значение и имя работают, как и оператор switch. Это просто состояние, которое не обновляется ***

Ответы [ 3 ]

1 голос
/ 05 августа 2020

Добро пожаловать в SO. Вы по-прежнему можете написать аналогичный код для примера this.setState, который вы предоставили с помощью useState. Вот пример, который можно быстро запустить.

Ответ, связанный с вашим проектом:

  1. Создайте компонент, который использует useContext, и просто загрузите нужные вам значения и метод handleChange
const Test = () => {
  const { type, capacity, handleChange } = React.useContext(RoomContext);

  console.log(type, capacity);

  return (
      <div>
        <select name="type" onChange={handleChange}>
            <option value="all">all</option>
            <option value="another">another</option>
            <option value="one">one</option>
        </select>
        <select name="capacity" onChange={handleChange}>
          <option value="1">1</option>
          <option value="50">50</option>
          <option value="100">100</option>
        </select>
      </div>
  )
};
Добавьте тестовый компонент в качестве дочернего для Поставщика комнат. Запустите приложение, и вы увидите, что оно обновится как обычно

Рабочие исполняемые примеры:

const target = e.target;
const value = e.type === "checkbox" ? target.checked : target.value;
const name = e.target.name;    
this.setState({ [name]: value });

const rootEl = document.getElementById('root');

const App = () => {
  const [form, setForm] = React.useState({
    name: '',
    checkbox: false,
  });
  
  const handleChange = (e) => {
    const target = e.target;
    const value = e.type === "checkbox" ? target.checked : target.value;
    const name = e.target.name;
    
    setForm(prevState => ({ ...prevState, [name]: value }));
  }
  
  return (
    
      
      
      
      
      {JSON.stringify(form)}
)} ReactDOM.render ( , rootEl);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Вот рабочий пример кода с несколькими useStates.

const rootEl = document.getElementById('root');

const App = () => {
  const [name, setName] = React.useState('');
  const [checkbox, setCheckbox] = React.useState(false);

  const handleChange = (e) => {
    const target = e.target;
    const value = e.type === "checkbox" ? target.checked : target.value;
    const name = e.target.name;
    
    switch (name) {
      case "name":
        setName(value);
        break;
      case "checkbox":
        setCheckbox(value);
        break;
      default:
        return;
    }
  };
  
  return (
    
      
      
      
      
      {JSON.stringify({ name, checkbox })}
)} ReactDOM.render ( , rootEl);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
1 голос
/ 05 августа 2020

Исправление моей проблемы заключалось в том, что это не было повторной визуализации, поэтому это был цикл за все время.

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

import React, { createContext, useState, useEffect } from "react";

import items from "../data";

export const RoomContext = createContext();

const RoomProvider = (props) => {
  const [rooms, setRooms] = useState([]);
  const [sortedRooms, setSortedRooms] = useState([]);
  const [featuredRooms, setFeaturedRooms] = useState([]);
  const [loading, setLoading] = useState(true);
  const [type, setType] = useState("all");
  const [capacity, setCapacity] = useState(1);
  const [price, setPrice] = useState(0);
  const [minPrice, setMinPrice] = useState(0);
  const [maxPrice, setMaxPrice] = useState(0);
  const [minSize, setMinSize] = useState(0);
  const [maxSize, setMaxSize] = useState(0);
  const [breakfast, setBreakfast] = useState(false);
  const [pets, setPets] = useState(false);

  //call the formatted data
  useEffect(() => {
    //set rooms
    const rooms = formatData(items);
    //set the featured rooms
    const featuredRooms = rooms.filter((room) => room.featured === true);
    //always show the max price as default
    const maxPrice = Math.max(...rooms.map((item) => item.price));
    //always show the max price as default
    const maxSize = Math.max(...rooms.map((item) => item.size));

    setRooms(rooms);
    setSortedRooms(rooms);
    setFeaturedRooms(featuredRooms);
    setLoading(false);
    setMaxPrice(maxPrice);
    setMaxSize(maxSize);
    setPrice(maxPrice);
  }, [
    type,
    capacity,
    price,
    minPrice,
    maxPrice,
    minSize,
    maxSize,
    breakfast,
    pets,
  ]);

  //format data is getting all the required fields we want to pull from the originl data
  const formatData = (items) => {
    let tempItems = items.map((item) => {
      const id = item.sys.id;
      const images = item.fields.images.map((image) => image.fields.file.url);

      const room = { ...item.fields, images: images, id: id };
      return room;
    });
    return tempItems;
  };

  const getRoom = (slug) => {
    let tempRooms = [...rooms];
    const room = tempRooms.find((room) => room.slug === slug);
    return room;
  };

  const handleChange = (e) => {
    const target = e.target;
    const value = e.type === "checkbox" ? target.checked : target.value;
    const name = e.target.name;

    switch (name) {
      case "type":
        setType(value);
        break;
      case "capacity":
        setCapacity(value);
        break;
      case "price":
        setPrice(value);
        break;
      case "minPrice":
        setMinPrice(value);
        break;
      case "maxPrice":
        setMaxPrice(value);
        break;
      case "minSize":
        setMinSize(value);
        break;
      case "maxSize":
        setMaxSize(value);
        break;
      case "breakfast":
        setBreakfast(value);
        break;
      case "pets":
        setPets(value);
        break;
      default:
        return;
    }
    console.log(name, value);
  };

  const filteredRooms = () => {
    let initialRooms = [...rooms];

    if (type !== "all") {
      initialRooms = initialRooms.filter((room) => room.type === type);
    }
    console.log("room type is", type);
    setSortedRooms(initialRooms);
  };

  return (
    <RoomContext.Provider
      value={{
        rooms,
        featuredRooms,
        getRoom,
        loading,
        sortedRooms,
        type,
        capacity,
        price,
        minPrice,
        maxPrice,
        minSize,
        maxSize,
        breakfast,
        pets,
        handleChange,
        filteredRooms,
      }}
    >
      {props.children}
    </RoomContext.Provider>
  );
};

export default RoomProvider;
0 голосов
/ 05 августа 2020

вы импортировали useState?

import React, {useState} from 'react';
...