从数组中删除信息时 React UseEffect 不更新
React UseEffect not updating when information is deleted from array
我一直在寻找帮助,因为我已经坚持了一段时间。我有一个与 Github API 交互的 MERN 堆栈应用程序。用户可以搜索 Github 用户并将他们保存到他们在应用程序上的个人资料中,一旦他们这样做,他们也会开始在 Github 上关注该用户。以同样的方式,用户可以从应用程序的个人资料中删除用户,这将在 Github 上取消关注同一用户。问题是,当我单击删除用户按钮时,它不会在浏览器上更新,除非我刷新页面然后我看到该用户已从已保存用户数组中删除。在 Profile.jsx 组件中,我呈现已保存用户的列表并从数据库中获取信息。在 SavedGithubUsersCard.jsx 组件中,我通过保存的用户数据进行映射以呈现用户的信息,例如姓名。在 DeleteButton.jsx 中,我在单击按钮时删除了特定的已保存用户。我的问题是我做错了什么?是道具更改未被触发还是 UseEffect 存在其他问题?
代码如下:
import React, { useEffect, useContext } from 'react';
import swal from 'sweetalert';
import { AppContext } from '../context/AppContext';
import SavedGithubUsersCard from './SavedGithubUsersCard';
import axios from 'axios';
Profile.jsx
const Profile = () => {
const {
githubUserData, setGithubUserData
} = useContext(AppContext);
useEffect(() => {
axios.get('/api/githubdata').then((res) => {
setGithubUserData(res.data);
})
.catch((err) => {
if (err) {
swal('Error', 'Something went wrong.', 'error');
}
});
}, [setGithubUserData]);
return (
<div className="profile-saved-users">
<div className="githubUserData-cards">
<h1 className="saved-users-header">Saved users</h1>
{!githubUserData || githubUserData.length === 0 ? (
<p className="no-saved-users-text">No saved users yet :(</p>
) : (
<SavedGithubUsersCard githubUserData={githubUserData}/>
)}
</div>
</div>
);
};
export default Profile;
import React from 'react';
import { Card, Button } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import DeleteButton from './DeleteButton';
SavedGithubUsersCard.jsx
const SavedGithubUsersCard = ({githubUserData}) => {
return (
<>
{githubUserData?.map(githubUserData => (
<Card key={githubUserData._id} id="saved-users-card">
<Card.Img
variant="top"
src={githubUserData.avatar_url}
id="saved-users-card-image"
/>
<Card.Body id="saved-users-card-information">
<Card.Title
id="saved-users-name"
style={{ textAlign: 'center' }}
>
{githubUserData.name}
</Card.Title>
<Card.Subtitle
id="saved-users-username"
className="mb-2 text-muted"
style={{ textAlign: 'center' }}
>
{githubUserData.login}
</Card.Subtitle>
<Card.Text id="saved-users-profile-url">
Profile URL: {githubUserData.html_url}
</Card.Text>
<Link
to={{ pathname: "githubUserData.html_url" }}
target="_blank"
>
<Button
id="saved-users-profile-button"
variant="outline-primary"
>
View profile
</Button>
</Link>
<DeleteButton githubUserDataId={githubUserData._id} githubUserDataLogin= {githubUserData.login} />
</Card.Body>
</Card>
))}
</>
);
};
export default SavedGithubUsersCard
DeleteButton.jsx
import React from 'react';
import { Button } from 'react-bootstrap';
import axios from 'axios';
import swal from 'sweetalert';
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const handleRemove = async () => {
try {
fetch(`https://api.github.com/user/following/${githubUserDataLogin}`, {
method: 'DELETE',
headers: {
Authorization: `token ${process.env.GITHUB_TOKEN}`
}
});
await axios({
method: 'DELETE',
url: `/api/githubdata/${githubUserDataId}`,
withCredentials: true
});
swal(
'Removed from profile!',
`You are no longer following ${githubUserDataLogin} on Github`,
'success'
);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
<Button
variant="outline-danger"
style={{ marginLeft: 20 }}
onClick={handleRemove}
id="saved-users-delete-button"
>
Remove User
</Button>
);
};
export default DeleteButton;
AppContext.jsx
import React, { createContext, useState, useEffect } from 'react';
import axios from 'axios';
const AppContext = createContext();
const AppContextProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [loading, setLoading] = useState(false);
const [githubUserData, setGithubUserData] = useState([]);
const user = sessionStorage.getItem('user');
useEffect(() => {
// incase user refreshes and context is cleared.
if (user && !currentUser) {
axios
.get(`/api/users/me`, {
withCredentials: true
})
.then(({ data }) => {
setCurrentUser(data);
})
.catch((error) => console.error(error));
}
}, [currentUser, user]);
return (
<AppContext.Provider
value={{ currentUser, setCurrentUser, loading, setLoading, githubUserData, setGithubUserData}}
>
{children}
</AppContext.Provider>
);
};
export { AppContext, AppContextProvider };
谢谢!
从我看到的你的代码来看,当你删除一个用户时,你在后端成功删除了他们,但也没有更新本地状态。
选项 1 - 重新获取用户列表并更新本地状态
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const { setGithubUserData } = useContext(AppContext);
const handleRemove = async () => {
try {
fetch(....);
await axios(....);
swal(....);
const usersDataRes = await axios.get('/api/githubdata');
setGithubUserData(usersDataRes.data);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
...
);
};
选项 2 - 尝试手动同步本地状态
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const { setGithubUserData } = useContext(AppContext);
const handleRemove = async () => {
try {
fetch(....);
await axios(....);
swal(....);
setGithubUserData(users =>
users.filter(user => user._id !== githubUserDataId)
);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
...
);
};
我一直在寻找帮助,因为我已经坚持了一段时间。我有一个与 Github API 交互的 MERN 堆栈应用程序。用户可以搜索 Github 用户并将他们保存到他们在应用程序上的个人资料中,一旦他们这样做,他们也会开始在 Github 上关注该用户。以同样的方式,用户可以从应用程序的个人资料中删除用户,这将在 Github 上取消关注同一用户。问题是,当我单击删除用户按钮时,它不会在浏览器上更新,除非我刷新页面然后我看到该用户已从已保存用户数组中删除。在 Profile.jsx 组件中,我呈现已保存用户的列表并从数据库中获取信息。在 SavedGithubUsersCard.jsx 组件中,我通过保存的用户数据进行映射以呈现用户的信息,例如姓名。在 DeleteButton.jsx 中,我在单击按钮时删除了特定的已保存用户。我的问题是我做错了什么?是道具更改未被触发还是 UseEffect 存在其他问题?
代码如下:
import React, { useEffect, useContext } from 'react';
import swal from 'sweetalert';
import { AppContext } from '../context/AppContext';
import SavedGithubUsersCard from './SavedGithubUsersCard';
import axios from 'axios';
Profile.jsx
const Profile = () => {
const {
githubUserData, setGithubUserData
} = useContext(AppContext);
useEffect(() => {
axios.get('/api/githubdata').then((res) => {
setGithubUserData(res.data);
})
.catch((err) => {
if (err) {
swal('Error', 'Something went wrong.', 'error');
}
});
}, [setGithubUserData]);
return (
<div className="profile-saved-users">
<div className="githubUserData-cards">
<h1 className="saved-users-header">Saved users</h1>
{!githubUserData || githubUserData.length === 0 ? (
<p className="no-saved-users-text">No saved users yet :(</p>
) : (
<SavedGithubUsersCard githubUserData={githubUserData}/>
)}
</div>
</div>
);
};
export default Profile;
import React from 'react';
import { Card, Button } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import DeleteButton from './DeleteButton';
SavedGithubUsersCard.jsx
const SavedGithubUsersCard = ({githubUserData}) => {
return (
<>
{githubUserData?.map(githubUserData => (
<Card key={githubUserData._id} id="saved-users-card">
<Card.Img
variant="top"
src={githubUserData.avatar_url}
id="saved-users-card-image"
/>
<Card.Body id="saved-users-card-information">
<Card.Title
id="saved-users-name"
style={{ textAlign: 'center' }}
>
{githubUserData.name}
</Card.Title>
<Card.Subtitle
id="saved-users-username"
className="mb-2 text-muted"
style={{ textAlign: 'center' }}
>
{githubUserData.login}
</Card.Subtitle>
<Card.Text id="saved-users-profile-url">
Profile URL: {githubUserData.html_url}
</Card.Text>
<Link
to={{ pathname: "githubUserData.html_url" }}
target="_blank"
>
<Button
id="saved-users-profile-button"
variant="outline-primary"
>
View profile
</Button>
</Link>
<DeleteButton githubUserDataId={githubUserData._id} githubUserDataLogin= {githubUserData.login} />
</Card.Body>
</Card>
))}
</>
);
};
export default SavedGithubUsersCard
DeleteButton.jsx
import React from 'react';
import { Button } from 'react-bootstrap';
import axios from 'axios';
import swal from 'sweetalert';
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const handleRemove = async () => {
try {
fetch(`https://api.github.com/user/following/${githubUserDataLogin}`, {
method: 'DELETE',
headers: {
Authorization: `token ${process.env.GITHUB_TOKEN}`
}
});
await axios({
method: 'DELETE',
url: `/api/githubdata/${githubUserDataId}`,
withCredentials: true
});
swal(
'Removed from profile!',
`You are no longer following ${githubUserDataLogin} on Github`,
'success'
);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
<Button
variant="outline-danger"
style={{ marginLeft: 20 }}
onClick={handleRemove}
id="saved-users-delete-button"
>
Remove User
</Button>
);
};
export default DeleteButton;
AppContext.jsx
import React, { createContext, useState, useEffect } from 'react';
import axios from 'axios';
const AppContext = createContext();
const AppContextProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [loading, setLoading] = useState(false);
const [githubUserData, setGithubUserData] = useState([]);
const user = sessionStorage.getItem('user');
useEffect(() => {
// incase user refreshes and context is cleared.
if (user && !currentUser) {
axios
.get(`/api/users/me`, {
withCredentials: true
})
.then(({ data }) => {
setCurrentUser(data);
})
.catch((error) => console.error(error));
}
}, [currentUser, user]);
return (
<AppContext.Provider
value={{ currentUser, setCurrentUser, loading, setLoading, githubUserData, setGithubUserData}}
>
{children}
</AppContext.Provider>
);
};
export { AppContext, AppContextProvider };
谢谢!
从我看到的你的代码来看,当你删除一个用户时,你在后端成功删除了他们,但也没有更新本地状态。
选项 1 - 重新获取用户列表并更新本地状态
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const { setGithubUserData } = useContext(AppContext);
const handleRemove = async () => {
try {
fetch(....);
await axios(....);
swal(....);
const usersDataRes = await axios.get('/api/githubdata');
setGithubUserData(usersDataRes.data);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
...
);
};
选项 2 - 尝试手动同步本地状态
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const { setGithubUserData } = useContext(AppContext);
const handleRemove = async () => {
try {
fetch(....);
await axios(....);
swal(....);
setGithubUserData(users =>
users.filter(user => user._id !== githubUserDataId)
);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
...
);
};