我正在 React 中开发一个 Top10UserList 组件,它从 api 获取前 10 个用户,然后为每个用户获取影像并成功地为每个用户创建一个影像标签,并且应该在他们自己的标签中显示每个用户的影像。
不幸的是,每个影像都共享相同的状态,因此它们都快速闪过所有 10 个影像,然后停留在最终影像上。
我需要它们分开,但我不确定如何重构我的代码来实作这一点。
反应组件:
const TOP_USERS_URL = 'http://localhost:8080/users/top-players'
const TOP_TEN_USERS_URL = 'http://localhost:8080/users/top-10-players'
const TOP_TEN_USERS_IMAGES_URL = 'http://localhost:8080/image-files/download-using-username'
const USER_IMG_URL = 'http://localhost:8080/image-files/'
class TopUserList extends Component {
constructor(props) {
super(props);
this.state = { users: [], top10Users: [], token: '', top10UsersImages: [], profUrl: '', profileImage: '' };
}
componentDidMount() {
fetch(TOP_USERS_URL, {
method: 'GET',
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": localStorage.getItem("token")
},
})
.then(response => response.json())
.then(data => this.setState({ users: data }));
fetch(TOP_TEN_USERS_URL, {
method: 'GET',
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": localStorage.getItem("token")
},
})
.then(response => response.json())
.then(data => {
this.setState({ top10Users: data });
console.log(data);
console.log("Data[0]")
console.log(data[0].username)
data.forEach(element => {
const imgUrl = USER_IMG_URL element.username;
const id = element.id;
fetch(imgUrl, {
method: 'GET',
headers: {
"Authorization": localStorage.getItem("token")
}
})
.then(r => r.arrayBuffer())
.then(buffer => {
const blob = new Blob([buffer]);
this.state.img = URL.createObjectURL(blob);
});
const fetchImage = async (url) => {
try {
const response = await fetch(url, {
headers: {
"Authorization": localStorage.getItem("token")
}
});
const imageBytes = await response.arrayBuffer();
var blob = new Blob([imageBytes], { type: "image/jpeg" });
var imageUrl = URL.createObjectURL(blob);
return imageUrl;
} catch (error) {
console.log("ERROR:", error);
}
};
const profileUrl = "profile-image-" id;
this.state.profUrl = profileUrl;
(async () => {
const imageSrc = await fetchImage(imgUrl);
console.log("ImageSRC:");
console.log(imageSrc);
console.log("Profile Url:");
console.log(profileUrl);
this.setState({ profileImage: imageSrc })
})();
console.log("Profile Url:");
console.log(profileUrl);
document.getElementById("app").innerHTML = `
<image id={profileUrl}>
`;
}
);
});
}
render() {
const { users, top10Users, isLoading, profileUrl, profileImage} = this.state;
console.log("Top 10 users data: ")
console.log(top10Users);
console.log("Top 10 users using index: ");
console.log(top10Users[0]);
console.log("ProfUrl: ");
console.log(profileUrl);
console.log("profImg");
console.log(profileImage);
if (isLoading) {
return <p>Loading...</p>;
}
const topUserList = users.map(user => {
return <tr key={user.id}>
<td style={{ whiteSpace: 'nowrap' }} class="player-list-key-text">{user.name}</td>
<td class="player-list-key-text">{user.username}</td>
<td class="player-list-key-text">{user.location}</td>
</tr>
});
const topTenUserList = top10Users.map(user => {
return <div className="user-container" key={user.id}>
<Card>
<div id="app"></div>
<img src={profileImage} style={{ width: 200, height: 200 }} />
<CardTitle>{user.name}</CardTitle>
</Card>
</div>
})
return (
<div className="outer-div-container">
<div>
<Container fluid>
<h3 className="player-list-header">Top Players</h3>
<Table className="mt-4">
<thead>
<tr id="player-list-row">
<th className="player-list-data-text">Name</th>
<th className="player-list-data-text">Username</th>
<th className="player-list-data-text">Location</th>
</tr>
</thead>
<tbody>
{topUserList}
</tbody>
</Table>
{topTenUserList}
</Container>
</div>
</div>
);
}
}
export default TopUserList;
结果:
我如何在 React 中做到这一点?我需要创建 10 个不同的影像状态值吗?
谢谢你的帮助!
更新代码:
class TopUserList extends Component {
constructor(props) {
super(props);
this.state = { users: [], top10Users: [], token: '', top10UsersImages: [], profUrl: '', profileImage: {} };
}
componentDidMount() {
fetch(TOP_USERS_URL, {
method: 'GET',
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": localStorage.getItem("token")
},
})
.then(response => response.json())
.then(data => this.setState({ users: data }));
fetch(TOP_TEN_USERS_URL, {
method: 'GET',
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": localStorage.getItem("token")
},
})
.then(response => response.json())
.then(data => {
this.setState({ top10Users: data });
console.log(data);
console.log("Data[0]")
console.log(data[0].username)
const profileImagesData = {}
data.forEach((element, userIndex) => {
const imgUrl = USER_IMG_URL element.username;
const id = userIndex;
fetch(imgUrl, {
method: 'GET',
headers: {
"Authorization": localStorage.getItem("token")
}
})
.then(r => r.arrayBuffer())
.then(buffer => {
const blob = new Blob([buffer]);
this.state.img = URL.createObjectURL(blob);
});
const fetchImage = async (url) => {
try {
const response = await fetch(url, {
headers: {
"Authorization": localStorage.getItem("token")
}
});
const imageBytes = await response.arrayBuffer();
var blob = new Blob([imageBytes], { type: "image/jpeg" });
var imageUrl = URL.createObjectURL(blob);
profileImageData[element?.id] = imageSrc
return imageUrl;
} catch (error) {
console.log("ERROR:", error);
}
};
const profileUrl = "profile-image-" id;
this.state.profUrl = profileUrl;
(async () => {
const imageSrc = await fetchImage(imgUrl);
console.log("ImageSRC:");
console.log(imageSrc);
console.log("Profile Url:");
console.log(profileUrl);
this.setState({profileImage:{...profileImageData}})
})();
console.log("Profile Url:");
console.log(profileUrl);
document.getElementById("app").innerHTML = `
<image id={profileUrl}>
`;
}
);
});
}
render() {
const { users, top10Users, isLoading, profileUrl, profileImage} = this.state;
console.log("Top 10 users data: ")
console.log(top10Users);
console.log("Top 10 users using index: ");
console.log(top10Users[0]);
console.log("ProfUrl: ");
console.log(profileUrl);
console.log("profImg");
console.log(profileImage);
if (isLoading) {
return <p>Loading...</p>;
}
const topUserList = users.map(user => {
return <tr key={user.id}>
<td style={{ whiteSpace: 'nowrap' }} class="player-list-key-text">{user.name}</td>
<td class="player-list-key-text">{user.username}</td>
<td class="player-list-key-text">{user.location}</td>
</tr>
});
const topTenUserList = top10Users.map(user => {
return <div className="user-container" key={user.id}>
<Card>
<div id="app"></div>
<img src={this.state.profileImage[user.id]} style={{ width: 200, height: 200 }} />
<CardTitle>{user.name}</CardTitle>
</Card>
</div>
})
return (
<div className="outer-div-container">
<div>
<Container fluid>
<h3 className="player-list-header">Top Players</h3>
<Table className="mt-4">
<thead>
<tr id="player-list-row">
<th className="player-list-data-text">Name</th>
<th className="player-list-data-text">Username</th>
<th className="player-list-data-text">Location</th>
</tr>
</thead>
<tbody>
{topUserList}
</tbody>
</Table>
{topTenUserList}
</Container>
</div>
</div>
);
}
}
export default TopUserList;
uj5u.com热心网友回复:
您可以通过将您的 profileImage 状态从字符串值转换为物件来实作,其中该物件的键将是您的用户 ID,值将是影像 url
在您的代码中,您可能需要进行以下更改
您
profileImage:''
在建构式中的状态变量应替换为profileImage:{}
在
componentDidMount
初始化const profileImageData = {}
此行上方的变量data.forEach(element
在下
const imageSrc = await fetchImage(imgUrl);
,一旦你得到回应,做profileImageData[element?.id] = imageSrc
(我假设你的每个 top10User 阵列都有一个 id 变量)替换
this.setState({ profileImage: imageSrc })
为this.setState({profileImage:{...profileImageData})
在您的 top10UserList 中,替换
<img src={profileImage} style={{ width: 200, height: 200 }} />
为<img src={this.state.profileImage[user.id]} style={{ width: 200, height: 200 }} />
如果您没有 id 值,那么您可以替换
data.forEach(element
为data.forEach((element, userIndex)
并userIndex
用作您的键值,而不是element.id
在 top10UserList 中执行相同操作
0 评论