我在这里所说的服务器基本上是一个列表项,其中包含一些数据,例如标题,标志等,
我基本上有两个“服务器”列表:
第一个包含收藏的服务器。另一个包含其他服务器。
每当有人“喜欢”服务器时,应将其项从第二个列表移至第一个列表,并且他的“心脏”应变为红色。
每当有人“不喜欢”服务器时,都会发生相同的过程,但是倒退:服务器应移至第二个列表,并且他的心又变灰。
我能够毫无问题地在列表之间移动元素,但是其渲染发生了奇怪的事情,我无法理解要解决的问题:
我在.gifv中记录了发生了什么:https://i.imgur.com/i5QHNml.gifv
我为此主题删除了无用的代码,但是它仍然很大,很抱歉。
ServerList.js
import * as React from 'react';
import { List, Collapse, ListItem, ListItemIcon, ListItemText, ListSubheader } from '@material-ui/core';
import { Favorite, Computer, ExpandLess, ExpandMore } from "@material-ui/icons";
import ServerListItem from "./ServerListItem";
import SearchBar from './SearchBar';
export default class ServerList extends React.Component {
onSearch(text) {
... things about searchbar, not worth to include ...
}
constructor(props) {
super(props);
this.state = {
offset: 0,
favoritesOpen: false,
allOpen: true,
};
this.onSearch = this.onSearch.bind(this);
this.serverList = this.props.servers
.sort((a, b) => { ... sorting servers ... })
.map((server) => {
return (
<ServerListItem
country={server.country}
hostname={server.hostname}
players={server.players}
maxplayers={server.maxplayers}
level={server.level}
host={server.endpoint}
onFavorited={ flag => {
let index = this.favorites.indexOf(server.hostname);
if(!flag && index >= 0){
this.favorites.splice(index, 1);
this.forceUpdate();
}
if(flag && index === -1){
this.favorites.push(server.hostname);
this.forceUpdate();
}
}}
/>
)
});
this.favorites = [];
}
render() {
let allServersFiltered = this.serverList
.filter((it) => { ... things about searchbar, not worth to include ... });
let otherServers = allServersFiltered
.filter((it, index) => (
!this.favorites.includes(it.props.hostname) &&
index >= this.state.offset && index < this.state.offset + 10
));
return(
<List
subheader={ ... things about searchbar, not worth to include ... }
>
<ListItem button onClick={() => { this.setState({favoritesOpen: !this.state.favoritesOpen}) }}>
<ListItemIcon>
<Favorite />
</ListItemIcon>
<ListItemText inset primary="Favorites" />
{ this.state.favoritesOpen ? <ExpandLess /> : <ExpandMore /> }
</ListItem>
{
<Collapse in={this.state.favoritesOpen} timeout={"auto"} unmountOnEdit>
<List component={"div"}>
{
this.favorites.length === 0
? <ListItemText inset primary={"You have no favorite servers :c"}/>
: this.serverList.filter((it) => this.favorites.includes(it.props.hostname))
}
</List>
</Collapse>
}
<List>
<ListItem button onClick={() => {this.setState({ allOpen: !this.state.allOpen })}}>
<ListItemIcon>
<Computer />
</ListItemIcon>
<ListItemText inset primary="All Servers" />
{ this.state.allOpen ? <ExpandLess /> : <ExpandMore /> }
</ListItem>
<Collapse in={this.state.allOpen} unmountOnEdit>
{
otherServers.length === 0
? <ListItemText inset primary={"No more servers found :c"}/>
: otherServers
}
</Collapse>
</List>
</List>
);
}
}
ServerListItem.js
import './ServerListItem.css'
import * as React from 'react';
import { Badge } from 'react-bootstrap'
import { ListItemSecondaryAction, ListItem, ListItemAvatar, Avatar, ListItemText,
IconButton } from "@material-ui/core";
import { Favorite } from '@material-ui/icons'
export default class ServerListItem extends React.Component{
constructor(props){
super(props);
this.state = { favorited: false };
this.toggleFavorite = this.toggleFavorite.bind(this);
}
toggleFavorite() {
if(this.props.onFavorited) this.props.onFavorited(!this.state.favorited); //calls onFavorite callback with the current state
this.setState({ favorited: !this.state.favorited });
}
render() {
let flag = `https://www.countryflags.io/${this.props.country}/shiny/64.png`;
return(
<ListItem>
<ListItemAvatar>
<Avatar src={flag} alt={this.props.flag}/>
</ListItemAvatar>
<ListItemText
primary={this.props.hostname}
secondary={ ... just the badges, not worth to include ... }
/>
<ListItemSecondaryAction>
<IconButton aria-label="Favorite" onClick={this.toggleFavorite}>
<Favorite className={ this.state.favorited && 'favorited' }/>
</IconButton>
</ListItemSecondaryAction>
</ListItem>
);
}
}
我阅读了一些有关在元素渲染时清除状态的内容,但是我不能很好地理解这个概念,并且在使它起作用方面应该做些困难。我也无法理解为什么我的代码会移动正确的元素,却会触发错误的元素(因为状态更改是在同一方法中调用的)。