reactjs - 获取正确的路由路径
问题描述
所以我正在尝试获取和显示属于团队的球员。我有一个下拉按钮,其中包含所述球队的选择,点击时,它应该呈现所选球队的球员。我遇到的问题是,在点击时,它会呈现我种子数据中的所有球员,与其所属的球队无关。我不确定我错过了什么,但这是我拥有的代码。在 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);
解决方案
调用您的操作创建者参数有点令人困惑params
,但我相信您需要从中访问(某些)id
属性才能正确构建您的请求 URL 路径。为参数提供更好、更有意义的名称对代码的可读性大有帮助。
export const fetchPlayers = teamId => {
return dispatch => {
dispatch({ type: 'LOADING_PLAYERS' });
fetch(`/api/teams/${teamId}/players`) // interpolate id into path string
.then(res => res.json())
.then(responseJSON => { dispatch({ type: 'ADD_PLAYERS', cards: responseJSON});
});
}
下一部分是使用来自处理程序的正确参数调用此操作。
// Playerfilter
handleTeamSelection = e => {
e.preventDefault();
const { target: { title }} = e;
this.props.setTeam(title);
this.props.fetchPlayers(title); // This is what I'm not sure about, but I'll get to that later
};
我无法立即从 react-bootstrap 文档中Dropdown.Item
判断它是否将额外的道具传递给孩子(即你的title
道具)或onClick
与onSelect
处理程序传递的内容(事件除外),或者它是否更像是一个 html 选择您的处理程序需要绑定到Dropdown
'onSelect
道具而不是每个项目的元素。
我还查看了您的 db 目录,尝试收集您的teams
架构以找出该id
字段是什么。teams
我注意到您的表与您的表没有任何关系players
,即players
表有一个team_id
看起来应该是外键的 teams
字段,因此您可以进行连接。也许这是设计使然,您不需要进行多表查询。
在邮递员中,当我输入“ http://localhost:3000/api/teams/1/players ”时,它会返回所有玩家,而不仅仅是属于 id 为 1 的团队的玩家
如果这是您的本地服务器没有返回过滤数据,那么这表明您的服务器代码存在问题,无法正确查询您的数据库并返回错误的结果。
我认为您应该首先解决您的数据库问题并确保它返回正确的响应,然后处理您的客户端代码以确保它正确地发出请求。
推荐阅读
- javascript - 如何正确使用 clearInterval
- typescript - NestJS - 测试 @Inject('Value') 依赖
- scala - 系统未在 GKE 上 docker 的 scala 应用程序中终止
- python - 带有事务的 Pandas to_sql
- arduino - 如何在 Verilog 中创建和使用任务
- php - PHPMailer 不会通过 localhost 发送电子邮件
- azure-functions - 沙盒 Blazor WebAssemblies 代替 AppDomain 沙盒
- python - 尝试使用 FastAPI 和 python-docx 库读取 docx 文件:AttributeError: 'bytes' object has no attribute 'seek' 错误
- python - Tkinter 回调中的异常:TypeError:float() 参数必须是字符串或数字,而不是“事件”
- c - Linux内核驱动程序挂钩系统调用不起作用