【问题标题】:Fetching proper route path获取正确的路由路径
【发布时间】: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 获取特定球队的所有球员并将他们显示在当前路线上?

标签: reactjs redux routes


【解决方案1】:

调用您的动作创建者参数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
};

我无法立即从 Dropdown.Item 上的 react-bootstrap 文档中判断它是否将额外的道具传递给孩子(即您的 title 道具)或 onClickonSelect 处理程序(其他而不是事件),或者它可能更像是一个 html 选择元素,您的处理程序需要绑定到 DropdownonSelect 道具而不是每个项目。

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

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

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

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

【讨论】:

  • 我修复了我的数据库问题,现在我可以看到 Postman 在我输入 ""localhost:3000/api/teams/1/players" 时返回了正确的玩家。但是我收到了 'TypeError: this.props.players.cards.map is在单击下拉按钮上的团队后尝试渲染玩家时,DataContainer 不是一个函数。我将玩家控制器的索引更改为“@players = Team.find(params[:team_id]).players”。来自“@players = Player.all”,这是导致问题的原因。不知道为什么。
  • 终端显示“ActiveRecord::RecordNotFound(找不到具有 'id'=Chaos 的团队):”我不知道应该如何设置我的玩家控制器以使其工作。
  • 您能否用这些进一步的问题更新您的问题,而不是在此处讨论答案?您的动作创作者中responseJSON 的形状是什么?如果它不是一个数组(或任何没有映射函数的对象),那么this.props.players.cards 将会失败。
  • 我更新了问题。我还使用您显示的代码编辑了 dataActions 和 Player Fitler 中的 fetchPlayers。 ActiveRecord 应该寻找 'id'=1 的团队,而不是寻找 'id'=Chaos,因为它不是根据名称寻找的,对吧?
猜你喜欢
  • 2020-05-10
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-14
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多