首页 > 解决方案 > 如何根据 URL 中的 /:elementId/ 正确路由呈现列表的组件

问题描述

我基本上是在使用 rails、react-router、react-redux、JavaScript 和 PostgreSQL 制作一个不和谐的克隆。我的服务器和频道都呈现,但我只想通过将每个服务器的频道路由到 #/servers/:serverId/channels 来呈现频道。我的 url 链接工作正常,但关于路线的一些事情(我认为)给了我 500 内部服务器错误:http://localhost:3000/api/servers/NaN/channels

我已经尝试过使用 activeChannel: true/false 来弄乱我的商店,但这似乎使事情变得更加复杂,因为这意味着改变我的商店。

server_index_item.jsx

import React from 'react';
import { Link, Route, NavLink } from 'react-router-dom';
import { withRouter } from 'react-router';
///
import ChannelIndexContainer from '../channels/channel_index_container';
import ChannelIndex from '../channels/channel_index';

class ServerIndexItem extends React.Component {
  render() {
    const { server, serverId, channelIds, activeChannels } = this.props;


    return (
      <div>

        <li className="server-index-item">
          <NavLink to={`/servers/${server.id}/channels`}>
            <span>{server.id}</span>
            <img className="discord-server-icon"
              src={server.image_url}
              alt={server.title} />
          </NavLink>

          <Route path="/servers/:serverId/channels"
            render={(props) => <ChannelIndexContainer {...props} serverId={serverId} channelIds={channelIds} activeChannels={activeChannels} />}></Route>
          </li>
      </div>
    );
  }

}

Channel_Index.jsx

import React from 'react';
import { Route, Link } from 'react-router-dom';
import ChannelIndexContainer from './channel_index_container';
import ChannelShow from './channel_show';

//
import TestRoute from '../test_components/test_route';

class ChannelIndex extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    this.props.requestServerChannels(this.props.serverId);
  }


  render() {
    const { channels, serverId, channelIds, activeChannels } = this.props;

    const channelFilter = channels.filter(channel => {
      return channel.server_id === serverId;
    });


    return(
      <div>
        <ul>
          {channelFilter.map(channel =>
            <ChannelShow
              key={channel.id}
              channel={channel}
              activeChannels={activeChannels}
              serverId={serverId} />)}

        </ul>
      </div>
    );
  }
}

和我的频道控制器

class Api::ChannelsController < ApplicationController

  def index
    @channels = Channel.where("server_id = ?", params[:server_id])
  end


  def show
    @channel = Channel.find(params[:id])
  end

end

当我单击服务器时,它会转到 /servers/:serverId/channels ,这就是我将它嵌套在路由中的方式,但它仍然呈现每个通道,而不仅仅是所单击服务器的通道,然后抛出:GET http://localhost:3000/api/servers/NaN/channels 500(内部服务器错误)。提前致谢!

标签: javascriptruby-on-railsreact-reduxreact-router

解决方案


好的,所以我最终改变了我的部分状态来解决这个问题,它实际上效果很好。首先,我制作了这些动作创建者:

export const TOGGLE_SERVER = "TOGGLE_SERVER";
export const UNTOGGLE_SERVER ="UNTOGGLE_SERVER";


export const toggleServer = (server_id) => ({
  type: TOGGLE_SERVER,
  server_id
});

export const unToggleServer = () => ({
  type: UNTOGGLE_SERVER,
});

然后我为我的商店制作了一个新的减速器,它将嵌套在实体中(以及服务器、通道、用户等)

import {
  TOGGLE_SERVER,
  UNTOGGLE_SERVER
} from '../actions/toggle_actions';

import merge from 'lodash/merge';

const toggleReducer = (state = {}, action) => {
  switch(action.type) {
    case TOGGLE_SERVER:
      const toggledServer = { ["serverId"]: action.server_id};
      return merge({}, state, toggledServer);
    case UNTOGGLE_SERVER:
      const nextState = merge({}, state);
      delete nextState["serverId"];
      return nextState;
    default:
      return state;
  }
};
export default toggleReducer;
const mapDispatchToProps = dispatch => ({
  toggleServer: (server_id) => dispatch(toggleServer(server_id)),
  unToggleServer: () => dispatch(unToggleServer()),
});

然后在 server_index_item.jsx 中:

class ServerIndexItem extends React.Component {
  constructor(props) {
    super(props);

  }

    handleClick(server_id) {
      this.props.unToggleServer();
      this.props.toggleServer(server_id);
    }


  render() {
    const { server, serverId, channelIds } = this.props;
    return (
      <div>

        <li className="server-index-item">
          <NavLink to={`/servers/${server.id}/channels`}>
            <span>{server.id}</span>
            <img className="discord-server-icon"
              src={server.image_url}
              alt={server.title} />
          </NavLink>
                       // here its a button for now
          <button onClick={() => this.handleClick(server.id)}>toggleTest</button>
          <ChannelIndexContainer serverId={serverId} channelIds={channelIds} />
        </li>
      </div>
    );
  }
}
export default ServerIndexItem;

最后,在我的 ChannelIndex 中,我检查了 channel.server_id === activeServerId 是否为真,如果为真则渲染频道。我的第一个松弛帖子,所以我有点不确定我的原始问题是否没有正确阐述,所以我希望我对自己问题的回答(使用不同的解决方案)可以弥补它。


推荐阅读