javascript - Array.includes 在反应组件加载时返回冲突结果
问题描述
我有一个Profile
组件,它在加载时调用 Django 服务器来获取一组表示已添加书签的配置文件的 ID。如果书签数组包含用户正在使用的配置文件的 ID(即,如果用户正在使用/profile/1
并且 if [1, 4, 6].includes(1)
),则应填写页面上的 img,否则应仅概述。用户可以单击 img,然后调用后端将该 ID 添加到数组中。再次单击它会将其从阵列中删除。
但是,由于一些我不明白的渲染顺序,img 没有正确切换到填充版本。
在这里,您可以看到组件的 devtools 信息InfoCard
,它是Profile
. 您还可以看到配置文件 1 在bookmarks
我传入的数组 prop 中InfoCard
,这isFavourite
也是正确的。是我在父级中执行isFavourite
的方法的结果, . 但是 img(名称旁边的粉红色书签轮廓)未填充。您还可以看到我在登录之前登录了三次。该控制台日志采用:的方法。includes()
Profile
false
true
render()
InfoCard
console.log(this.props.isFavourite);
这是我编写所有这些的方式:
Profile.js
const [bookmarks, setBookmarks] = useState([]);
const [isFavourite, setIsFavourite] = useState(false);
const isUser = checkUser(
localStorage.getItem("CONNECTORY_userId"),
match.params.userId
);
const changeId = parseInt(localStorage.getItem("CONNECTORY_changeId"));
useEffect(() => {
async function fetchBookmarks() {
const bookmarksData = await fetch(
`${config.url}/profile/favouriteProfiles/${changeId}`
).then((res) => res.json());
const reducedBookmarksData = bookmarksData.map(({ id }) => id);
setBookmarks(reducedBookmarksData);
const isFavouriteCheck =
reducedBookmarksData.length > 0
? reducedBookmarksData.includes(parseInt(match.params.userId, 10))
: false;
setIsFavourite(isFavouriteCheck);
}
fetchBookmarks();
}, [match.params.userId, history, changeId, isFavourite]);
const handleChildBookmarkClick = async (id) => {
await fetch(`${config.url}/user/favourites/${changeId}/${id}`);
};
return (
<>
{profileData && (
<InfoCard
data={profileData}
experienceData={
profileData.experience ? profileData.experience[0] : null
}
isUser={isUser}
isFavourite={isFavourite}
bookmarks={bookmarks}
handleBookmarkClick={handleChildBookmarkClick}
/>
)}
</>
);
InfoCard.js
export default class InfoCard extends Component {
constructor(props) {
super(props);
this.state = {
favourite: this.props.isFavourite,
};
}
componentDidMount = () => {
this.setState({ favourite: this.props.isFavourite });
};
handleBookmarkClick = () => {
if (this.props.isUser) {
return;
}
this.props.handleBookmarkClick(this.props.data.id);
this.setState((prevState) => ({ favourite: !prevState.favourite }));
};
render() {
console.log(this.props.isFavourite);
...
{!this.props.isUser && (
<button
className="bookmark-container"
onClick={this.handleBookmarkClick}
>
<img
className="info-card-bookmark"
src={this.state.favourite ? bookmarkFull : bookmarkEmpty}
alt="Add this profile to your bookmarks"
/>
</button>
)}
...
我是否以正确的顺序渲染事物?我认为它也可能与异步函数有关,我也有点弱。
解决方案
下面的代码:
const handleChildBookmarkClick = async (id) => {
await fetch(`${config.url}/user/favourites/${changeId}/${id}`);
};
请求成功时什么都不做。如果我理解正确,它应该调用setIsFavourite
或以某种方式触发fetchBookmarks
,以便 Profile 重新获取数据并更新状态(这似乎有点矫枉过正)。
下面的代码看起来也很可疑:
componentDidMount = () => {
this.setState({ favourite: this.props.isFavourite });
};
您应该直接使用道具 likethis.props.isFavourite
或使用getDerivedStateFromProps
. 将 props 克隆到 state 通常不是一个好主意,因为它断开了父子关系并复制了 state。
例如,在这种情况下,您最终没有更新isFavourite
Profile 的状态。isFavourite
应该只存在于一个地方。
推荐阅读
- node.js - 如何在不使用索引的情况下更新 dynamodb 中的映射对象列表?
- maven - 在 rpm-maven-plugin 中有条件地将文件从源位置复制到目标位置
- docker - RabbitMQ 客户端在运行 docker-compose up 命令时抛出错误
- javascript - 修改现有的数学序列数组
- selenium-webdriver - 硒拖放方法在chrome浏览器上不起作用
- python - .copy() 之后无法从数据框中打印列表
- javascript - Vanilla JS:根据光标位置选择父级中具有类的所有元素
- java - C ++来自不同线程的相同互斥锁的多个锁
- c# - 您可以更改默认情况下 OracleConnection 使用的提供程序吗?
- excel - Excel VBA - 使用 If 条件填充数组