如何解决在ReactJS中点击按钮更改状态后,React不会重新渲染预设
根据用户是否是房间的一部分,我将显示两个不同的按钮。如果用户是房间的一部分,则可以单击LEAVE,这将执行API调用。然后,我想重新加载组件并使按钮显示JOIN(因为它们不再是该房间的一部分)。
import JoinedRooms from '../../components/matrix_joined_rooms';
import JoinRoom from '../../components/matrix_function_join_room';
import LeaveRoom from '../../components/matrix_function_leave_room';
import { useEffect,useState } from 'preact/hooks';
const JoinLeaveButton = ({ name,roomId }) => {
const joinedRooms = JoinedRooms();
const [x,setX] = useState(5);
useEffect(() => console.log("re-render because x changed:",x),[x])
const handleXClick = (number) => {
setX(number)
}
if (joinedRooms.includes(name)) {
return <button name={roomId} onClick={() => {
LeaveRoom(roomId);
handleXClick(10);
}
}>LEAVE</button>
} else {
return <button name={roomId} onClick={() => {
JoinRoom(roomId);
handleXClick(20);
}
}>JOIN</button>
}
}
export default JoinLeaveButton;
我的JoinRoom和LeaveRoom组件是一个简单的API调用,如下所示:
const JoinRoom = (roomId) => {
fetch(`https://example.com/_matrix/client/r0/rooms/${roomId}/join`,{
method: "POST",headers: {
Authorization: `Bearer ${localStorage.getItem("mx_access_token")}`
}
});
}
export default JoinRoom;
按钮本身具有功能,问题是我必须手动重新加载页面才能使其正确显示。
我已经放置了一个虚拟状态,只要您按下该按钮便会执行该状态,它也会正确登录到控制台。 我的印象是,更改状态应重新呈现React中的组件(或在这种情况下为preact)。
谢谢!
解决方法
本质上:您需要将已加入房间的状态存储在某个位置,并在用户每次加入或离开房间时更新该状态。
我在这里过分了,但是像这样的自定义钩子很有意义:
// api calls
const fetchRooms = async userid => { ... }
const joinRoom = async (userId,roomId) => { ... }
const leaveRoom = async (userId,roomId) => { ... }
// custom hook
const useRooms = (userId) => {
const [fetching,setFetching] = useState(true);
const [error,setError] = useState(false);
// joinedRooms state is an empty array when this hook is first used
// it will be updated later using the useEffect hook
// or via the join or leave functions below
const [joinedRooms,setJoinedRooms] = useState([]);
// when the component that uses this hook is mounted
// or the user id changes,update the state
useEffect(() => {
let canceled;
setFetching(true);
(async() => {
try {
const rooms = await fetchRooms(userId);
canceled || setJoinedRooms(rooms);
} catch(err) {
canceled || setError(error);
} finally {
canceled || setFetching(false);
}
})();
return () => canceled = true;
},[userId]);
const leave = async roomId => {
try {
await leaveRoom(userId,roomId)
// alternatively you could fetch all the user rooms again here
setJoinedRooms(joined => joined.filter(r => r !== roomId));
} catch(err) {
// couldn't leave the room - what do you want to do with the state?
}
}
const join = async roomId => {
try {
await joinRoom(userId,roomId);
// alternatively you could fetch all the user rooms again here
setJoinedRooms(joined => [...joined,roomId]);
} catch(err) {
// couldn't join the room - what do you want to do with the state?
}
}
return {
fetching,error,joinedRooms,leave,join
}
}
在组件中,您将使用如下所示的内容:
const Rooms = (userId,listOfAllYourRoomIds) => {
const { joinedRooms,fetching,join,leave } = useRooms(userId);
// the `join` and `leave` functions are what you'll call
// when a user wants to join or leave a room,the joinedRooms prop will get
// updated according,and everything will "just work"
return listOfAllYourRoomIds.map(roomId => <SomeRoomComponent roomId={roomId}/>)
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。