javascript - 将上下文 API 类更改为 React 中的函数挂钩
问题描述
我试图将“上下文 API”的“类组件”更改为“钩子”,但我已经徘徊了几个小时并被卡住了。在“类组件”环境中运行良好。但是“钩子”不起作用。
在课堂上,在 'filterRoom()' 中,tempRooms 变量 'filter(((room===>room.type===type);' 成为过滤器,但在挂钩中,整个 tempRooms 被输出而不是过滤器。
详细代码在我的 GitHub 中。
在分支中,master 用 hook 做,class 用 class 做。GitHub地址
https://github.com/lhk3337/beachResort。
上下文.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;
下面是一个关于如何在 Home 组件中使用上下文的示例:
import { useRoomContest } from "./whatever";
const Home = () => {
const { getRoom, handleChane, ...rest } = useRoomContext();
// here you can access all the date from the context
return (
<div>
</div>
)
};
推荐阅读
- javascript - 如何将 CRM javascript 值设置为 null?
- c++ - 我如何将向量作为类的成员进行迭代,而相应的对象作为 const 传递
- sql-server - VBA SQL Server查询连接但不返回记录
- javascript - 如何在不破坏 webpack 用户的情况下依赖可选的原生模块?
- python - Pygame 仅在从编辑器运行时工作
- javascript - Javascript:限制索引周围的数组
- firebase - firebase 可以处理多少用户?
- java - redis模板有查询语言吗?
- node.js - NodeJS 以 JSON 格式获取 LDAP 用户
- python - 有没有办法在使用熊猫按第三列中的值分组时将两列中的值相乘?