首页 > 解决方案 > 获取正确的路由路径

问题描述

所以我正在尝试获取和显示属于团队的球员。我有一个下拉按钮,其中包含所述球队的选择,点击时,它应该呈现所选球队的球员。我遇到的问题是,在点击时,它会呈现我种子数据中的所有球员,与其所属的球队无关。我不确定我错过了什么,但这是我拥有的代码。在 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);

标签: reactjsreduxroutes

解决方案


调用您的操作创建者参数有点令人困惑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道具)或onClickonSelect处理程序传递的内容(事件除外),或者它是否更像是一个 html 选择您的处理程序需要绑定到Dropdown'onSelect道具而不是每个项目的元素。

我还查看了您的 db 目录,尝试收集您的teams架构以找出该id字段是什么。teams我注意到您的表与您的表没有任何关系players,即players表有一个team_id看起来应该是外键 teams字段,因此您可以进行连接。也许这是设计使然,您不需要进行多表查询。

在邮递员中,当我输入“ http://localhost:3000/api/teams/1/players ”时,它会返回所有玩家,而不仅仅是属于 id 为 1 的团队的玩家

如果这是您的本地服务器没有返回过滤数据,那么这表明您的服务器代码存在问题,无法正确查询您的数据库并返回错误的结果。

我认为您应该首先解决您的数据库问题并确保它返回正确的响应,然后处理您的客户端代码以确保它正确地发出请求。


推荐阅读