显示从 React 中的 API 获取的用户图像列表,所有 10 张图像都闪烁到每个用户图像,然后第 10 个用户图像保留?

List of user images feched from API in React are displayed and all 10 images flash to each user image then the 10th user image stays?

我正在 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;

您可以通过将您的 profileImage 状态从字符串值转换为一个对象来实现,该对象的键将是您的用户 ID,值将是图像 url

在您的代码中,您可能需要进行以下更改

  1. 构造函数中的状态变量 profileImage:'' 应该 替换为 profileImage:{}

  2. componentDidMount 这一行上面初始化一个变量const profileImageData = {}data.forEach(element

  3. const imageSrc = await fetchImage(imgUrl);下,一旦你有回应,做 profileImageData[element?.id] = imageSrc(我假设你的每个人都有一个 id 变量 top10用户数组)

  4. this.setState({ profileImage: imageSrc })替换为 this.setState({profileImage:{...profileImageData})

  5. 在您的 top10UserList 中,将 <img src={profileImage} style={{ width: 200, height: 200 }} /> 替换为 <img src={this.state.profileImage[user.id]} style={{ width: 200, height: 200 }} />

    如果你没有id值那么你可以替换 data.forEach(elementdata.forEach((element, userIndex) 并使用 userIndex 作为键值而不是 element.id 并在 top10UserList 中也做同样的事情