简体   繁体   中英

Change Context API Class to function hooks in React

I tried to change the 'Class component' of 'Context API' to 'Hooks' but I've been wandering around for hours and getting stuck. Works well in a 'Class component' environment. But 'hooks' doesn't work.
In class, In 'filterRoom()' the tempRooms variable 'filter(((room===>room.type===type);' becomes a filter, but in hooks the whole tempRooms is output instead of a filter.

The detailed code is in my GitHub.
Among the branches, the master did it with hook and class did it with class. GitHub Address
https://github.com/lhk3337/beachResort .

Context.js

import React, { Component } from "react";
import items from "./data";
const RoomContext = React.createContext();

class RoomProvider extends Component {
  state = {
    rooms: [],
    sortedRooms: [],
    featuredRooms: [],
    loading: true,
    type: "all",
    capacity: 1,
    price: 0,
    minPrice: 0,
    maxPrice: 0,
    minSize: 0,
    maxSize: 0,
    breakfast: false,
    pets: false,
  };

  componentDidMount() {
    let rooms = this.formatdata(items);
    let featuredRooms = rooms.filter((room) => room.featured === true);
    let maxPrice = Math.max(...rooms.map((item) => item.price));
    let maxSize = Math.max(...rooms.map((item) => item.size));
    this.setState({
      rooms,
      featuredRooms,
      sortedRooms: rooms,
      loading: false,
      price: maxPrice,
      maxPrice,
      maxSize,
    });
  }

  formatdata = (items) => {
    let tempItem = items.map((item) => {
      let id = item.sys.id;
      let images = item.fields.images.map((image) => image.fields.file.url);
      let rooms = { ...item.fields, images, id };
      return rooms;
    });
    return tempItem;
  };

  getRoom = (slug) => {
    let tempRooms = [...this.state.rooms];
    const room = tempRooms.find((room) => room.slug === slug);
    return room;
  };
  handleChange = (event) => {
    const { target } = event;
    const value = event.type === "checkout" ? target.checked : target.value;
    const { name } = target;
    this.setState(
      {
        [name]: value,
      },
      this.filterRooms
    );
  };
  filterRooms = () => {
    let {
      rooms,
      type,
      capacity,
      price,
      minSize,
      maxSize,
      breakfast,
      pets,
    } = this.state;
    let tempRooms = [...rooms];
    if (type !== "all") {
      tempRooms = tempRooms.filter((room) => room.type === type);
    }
    this.setState({
      sortedRooms: tempRooms,
    });
  };
  render() {
    return (
      <RoomContext.Provider
        value={{
          ...this.state,
          getRoom: this.getRoom,
          handleChange: this.handleChange,
        }}
      >
        {this.props.children}
      </RoomContext.Provider>
    );
  }
}
const RoomConsumer = RoomContext.Consumer;
export function withRoomConsumer(Component) {
  return function ConsumerWrapper(props) {
    return (
      <RoomConsumer>
        {(value) => <Component {...props} context={value} />}
      </RoomConsumer>
    );
  };
}
export { RoomProvider, RoomConsumer, RoomContext };
import { createContext, useContext, useEffect, useState } from "react";
import items from "./data";

const RoomContext = createContext();

const useRoomContext = useContext(RoomContext);

const RoomProvider = ({ children }) => {
  const [state, setState] = useState({
    rooms: [],
    sortedRooms: [],
    featuredRooms: [],
    loading: true,
    type: "all",
    capacity: 1,
    price: 0,
    minPrice: 0,
    maxPrice: 0,
    minSize: 0,
    maxSize: 0,
    breakfast: false,
    pets: false,
  });

  useEffect(() => {
    const rooms = formatdata(items);
    const featuredRooms = rooms.filter((room) => room.featured === true);
    const maxPrice = Math.max(...rooms.map((item) => item.price));
    const maxSize = Math.max(...rooms.map((item) => item.size));
    setState((prevState) => {
      return {
        ...prevState,
        featuredRooms,
        sortedRooms: rooms,
        loading: false,
        price: maxPrice,
        maxPrice,
        maxSize,
      };
    });
  }, []);

  const formatdata = (items) => {
    const tempItem = items.map((item) => {
      const id = item.sys.id;
      const images = item.fields.images.map((image) => image.fields.file.url);
      const rooms = { ...item.fields, images, id };
      return rooms;
    });
    return tempItem;
  };

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

  const handleChange = (event) => {
    const { target } = event;
    const value = event.type === "checkout" ? target.checked : target.value;
    const { name } = target;
    setState((prevState) => {
      return {
        ...prevState,
        [name]: value,
      };
    });
    filterRooms();
  };

  const filterRooms = () => {
    let { rooms, type } = state;

    const tempRooms = [...rooms];

    if (type !== "all") {
      tempRooms = tempRooms.filter((room) => room.type === type);
    }

    setState((prevState) => {
      return {
        ...prevState,
        sortedRooms: tempRooms,
      };
    });
  };

  return (
      <RoomContext.Provider value={{
          ...state,
          getRoom,
          handleChange
      }}>
          <Home/>
      </RoomContext.Provider>
  )
};

export { useRoomContext };
export default RoomProvider;

Below is an example on how to use context in Home component:

import { useRoomContest } from "./whatever";

const Home = () => {
    const { getRoom, handleChane, ...rest } = useRoomContext(); 
    // here you can access all the date from the context
    
    return (
        <div>

        </div>
    )
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM