【发布时间】:2020-04-23 01:14:37
【问题描述】:
所以我试图获取并显示属于球队的球员。我有一个下拉按钮,其中包含所述球队的选择,点击时,它应该呈现所选球队的球员。我遇到的问题是,在点击时,它会呈现我的种子数据中的所有球员,与其所属的球队无关。我不确定我错过了什么,但这是我拥有的代码。在 Postman 中,当我输入“http://localhost:3000/api/teams/1/players”时,它会返回所有玩家,而不仅仅是属于 id 为 1 的团队的玩家。
编辑:我修复了过滤数据的问题,因为现在 Postman 中的 url "http://localhost:3000/api/teams/1/players" 可以正常工作。但是,当它在单击下拉按钮上的团队后尝试渲染玩家时,我从 DataContainer 收到“TypeError:this.props.players.cards.map is not a function”。我所做的只是更改控制器中的索引。终端还显示“ActiveRecord::RecordNotFound(找不到具有 'id'=Chaos 的团队):”
这是我的玩家控制器:
class PlayersController < ApplicationController
before_action :set_params, only: [:show]
def index
@players = Team.find(params[:team_id]).players
render json: @players, status: 200
end
def show
render json: @player, status: 200
end
private
def player_params
params.require(:player).permit(:name, :player_type, :cost,
:movement_allowance, :strength, :agility, :armour_value, :skills,
:team_id)
end
def set_params
@player = Player.find(params[:id])
end
包含下拉按钮的过滤器文件(已编辑):
class PlayerFilter extends Component {
constructor() {
super();
this.state = { data: [] };
}
async fetchButtonTeams() {
const response = await fetch(`/api/teams`);
const json = await response.json();
this.setState({ data: json });
}
componentDidMount(){
this.fetchButtonTeams()
}
handleTeamSelection = e => {
e.preventDefault();
const { target: { title }} = e;
this.props.setTeam(title);
this.props.fetchPlayers(title);
};
render() {
return (
<Container>
<Row>
<DropdownButton id="dropdown-player-button" title={this.props.team}>
{this.state.data.map(team => (
<div key={team}>
<Dropdown.Item onClick={this.handleTeamSelection} title={team.name}>{team.name}</Dropdown.Item>
</div>
))}
</DropdownButton>
</Row>
</Container>
)
}
}
const mapStateToProps = state => {
return {
team: state.players.team
}
};
const mapDispatchToProps = dispatch => {
return {
fetchPlayers: params => dispatch(fetchPlayers(params)),
fetchTeams: params => dispatch(fetchTeams(params)),
setTeam: team => dispatch({ type: "SET_TEAM", team })
}
};
export default connect(mapStateToProps, mapDispatchToProps)(PlayerFilter)
过滤器中调用了我的播放器获取(已编辑)
export const fetchPlayers = teamId => {
return dispatch => {
dispatch({ type: 'LOADING_PLAYERS' });
fetch(`/api/teams/${teamId}/players`)
.then(res => res.json())
.then(responseJSON => { dispatch({ type: 'ADD_PLAYERS', cards: responseJSON})
})
}
我的数据容器:
class DataContainer extends Component {
displayCards = () => {
switch(this.props.path) {
case "teams":
return (this.props.teams.cards.map(card => (
<NavLink style={{ color: "black" }} to={`/teams/${card.id}`} key={card.id}><TeamCard info={card} /></NavLink>
)));
case "players":
return (this.props.players.cards.map(card => (
<NavLink style={{ color: "black" }} to={`/players/${card.id}`} key={card.id}><PlayerCard info={card} /></NavLink>
)));
default:
return (<div>Empty</div>)
}
};
render() {
return (
<CardColumns>
{this.displayCards()}
</CardColumns>
)
}
}
const mapStateToProps = state => {
return {
teams: state.teams,
players: state.players
}
};
export default connect(mapStateToProps)(DataContainer)
我的 app.js:
import React from 'react';
import './App.css';
import { connect } from 'react-redux'
import NavButtonsContainer from './containers/NavButtonsContainer';
import DataContainer from "./containers/DataContainer";
import PlayerDisplay from "./components/PlayerDisplay";
import PlayerFilter from "./components/PlayerFilter";
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row"
import Col from "react-bootstrap/Col"
const App = props => {
return (
<Container>
<Router>
<Switch>
<Route path="/teams/:id">
<TeamDisplay info={props.info} />
</Route>
<Route path="/players/:id">
<PlayerDisplay info={props.info} />
</Route>
<Route path="/teams">
<Row>
<Col><TeamFilter path="teams" /></Col>
</Row>
<Row>
<NavButtonsContainer />
</Row>
<Row>
<DataContainer path="teams" />
</Row>
</Route>
<Route path="/players">
<Row>
<Col><PlayerFilter path="players" /></Col>
</Row>
<Row>
<NavButtonsContainer />
</Row>
<Row>
<DataContainer path="players" />
</Row>
</Route>
<Route path="/">
<NavButtonsContainer />
</Route>
</Switch>
</Router>
</Container>
);
};
const mapStateToProps = state => {
return {
info: state.piece
}
};
export default connect(mapStateToProps)(App);
【问题讨论】:
-
您的
fetchPlayers正在从您的服务器可能无法处理的文字字符串“/api/teams/:id/players”中获取。您可能打算从下拉菜单中推送/导航到您的“/api/teams/:id/players”路线(即 push(/api/teams/${team.id}/players)),然后在安装时拉取路线的匹配参数并进行抓取请求获取特定球队的球员。如果您可以分享您的响应数据形状,以及您的应用程序和路由器的组件,我们将有更好的布局,我们可能会为您指明正确的方向。 -
或者您实际上并没有进行 any 路由,您只需要从
fetchPlayers中传递的params正确构建获取 URL。队名和id一样吗?我认为您的fetchPlayers需要重新修改一下。奇怪的是它有点类似于异步操作。您正在使用基于类的组件,因此很明显您没有使用useReducer或任何 redux 钩子,但不清楚您要在这里完成什么。 -
@Drew Reese 我添加了应用程序。标题是团队名称,因为这是我希望下拉按钮显示的内容。 player reducer 还有一个 set team case 负责实际显示选择了哪个团队。你能展示一下应该如何用下拉按钮语法编写推送吗?
-
@DrewReese 我如何显示响应数据?
-
当然可以,但我需要更多详细信息。
id值与 URL 中没有它的路由有何关联?它来自何处?我认为我最初的假设是您尝试从渲染PlayerFilter的“/players”导航到另一条路线是不正确的。您是否只是想通过id获取特定球队的所有球员并将他们显示在当前路线上?