我见过很多类似的问题,但不知何故,通常的答案对我来说不起作用。
我有一个从API加载的项目的简单列表,见截图。当我按下“设置封面”按钮时,我希望项目被刷新,“设置封面”出现在另一个项目上。API清除所有cover
属性,并将其设置在选定的项目上。
下面是列表的代码:
import React, {useEffect, useState} from "react";
import ImageItem from "./ImageItem";
export default function ImageForm({reviewId}) {
const [items, setItems] = useState([]);
function setCover(id) {
const newList = items.map((item) => {
return {
...item,
cover: (item.id === id),
};
});
console.log('newlist', newList);
setItems(newList);
}
const loadList = () => {
fetch("/api/review/" + reviewId + "/images")
.then((res) => res.json())
.then((json) => {
console.log('useEffect', json);
setItems(json);
});
}
useEffect(() => {
loadList();
}, []);
return (
<>
<div className="row">
<div className="col col-sm-6">
{items.map((data) => {
return <ImageItem key={data.id}
data={data}
reload={loadList}
makeCover2={setCover}
/>;
})}
</div>
</div>
</>
);
}
And this is the code for the item Component:
这是项目Component的代码:
import React, {useState, useRef, useEffect} from "react";
import axios from "axios";
import {Dropdown} from "react-bootstrap";
export default function ImageItem({data, remove, reload, makeCover2}) {
const [imageData, setImageData] = useState(data);
const makeCover = async function (item) {
axios.post('/api/image/' + imageData.id + '/setcover').then(res => {
if (res.data.errors) {
console.error(res.data.errors);
} else {
makeCover2(imageData.id);
}
}).catch(err => {
console.error(err);
})
}
return (<div className="row my-2 py-2 image-item">
<div className="col p-0 m-0">
<div className="row">
<div className="col">
<img className="img-fluid" alt="" src={'/upload/img/' + imageData.image_name}/>
</div>
<div className="col text-end">
<Dropdown>
<Dropdown.Toggle variant="success" id="dropdown-basic">Actions</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item as="button" onClick={() => setShowForm(true)}>Change comment</Dropdown.Item>
{!imageData.cover && <Dropdown.Item as="button" onClick={makeCover}>Set cover</Dropdown.Item>}
<Dropdown.Item as="button" onClick={() => remove(imageData.id)}>Delete</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</div>
</div>
</div>
</div>)
}
我尝试了两种方法:
- 调用一个函数
makeCover2
,在API完成更新行和..之后更新列表中的所有项。 - 调用一个reload函数,该函数只调用
loadList
函数,再次从API获取所有项。
在这两种情况下,Set cover
下拉选项都停留在列表中的同一个项目上。但是在点击它之后,它应该跳转到另一个项目。这是怎么回事?
2条答案
按热度按时间plicqrtu1#
您已经将
data
属性复制到状态变量中。data
中的值仅在第一次渲染时检查,以设置imageData
的初始值。之后对data
的更改将不会对imageData
产生影响。我看不出状态存在的理由,所以我建议您通过删除状态并直接使用prop来解决这个问题:
14ifxucb2#
问题似乎出在
ImageItem
组件的状态更新上。你可以尝试使用一个useEffect
钩子,当data
属性改变时,它会更新状态:通过这样做,
imageData
将始终反映从父组件传递的最新数据属性。我希望这有帮助!