You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Rails问答应用:如何通过show路由实现单题展示

Fixing Single Question View in Your Rails API + React App

Hey there! Let's work through this step by step to get your single question view working as expected. The issue right now is that your React app isn't distinguishing between the list view (index) and single question view (show)—so we'll fix both the backend setup and frontend routing/data fetching.

First: Make Sure Your Rails API's Show Endpoint is Working

Before touching React, let's confirm your Rails backend is returning the right data for a single question.

  1. Check your routes: Ensure you have resources :questions in config/routes.rb—this automatically sets up the GET /questions/:id route for the show action.
  2. Update your QuestionsController: Make sure the show action returns a single question as JSON:
    # app/controllers/questions_controller.rb
    def show
      @question = Question.find(params[:id])
      render json: @question
    end
    
  3. Test the endpoint: Open Postman or run curl http://localhost:3000/questions/1 in your terminal. You should get a JSON object for just that one question, not an array of all questions. If this returns a list, double-check your controller code!

Next: Set Up React Router to Distinguish Routes

The main reason both URLs show the same content is that your React app isn't routing to different components for the list vs single question. We'll use React Router (v6, the latest stable version) to fix this.

  1. Install React Router: If you haven't already, run this in your React project folder:
    npm install react-router-dom
    
  2. Configure routes in your App component: Wrap your app with BrowserRouter and define separate routes for the list and single question:
    // src/App.js
    import { Routes, Route } from 'react-router-dom';
    import QuestionList from './components/QuestionList';
    import QuestionShow from './components/QuestionShow';
    
    function App() {
      return (
        <div className="App">
          <Routes>
            {/* Root path shows the list of questions */}
            <Route path="/" element={<QuestionList />} />
            {/* List view */}
            <Route path="/questions" element={<QuestionList />} />
            {/* Single question view - :id is a dynamic parameter */}
            <Route path="/questions/:id" element={<QuestionShow />} />
          </Routes>
        </div>
      );
    }
    
    export default App;
    
  3. Wrap your app with BrowserRouter: In your index.js, make sure to wrap the App component so routing works:
    // src/index.js
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { BrowserRouter } from 'react-router-dom';
    import App from './App';
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <BrowserRouter>
        <App />
      </BrowserRouter>
    );
    

Create the QuestionShow Component

Now build the component that fetches and displays a single question. We'll use useParams to grab the question ID from the URL and useEffect to fetch the data from your Rails API.

// src/components/QuestionShow.js
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';

function QuestionShow() {
  const [question, setQuestion] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const { id } = useParams(); // Grabs the :id from the URL

  useEffect(() => {
    const fetchSingleQuestion = async () => {
      try {
        const response = await fetch(`http://localhost:3000/questions/${id}`);
        if (!response.ok) throw new Error('Could not load question');
        
        const questionData = await response.json();
        setQuestion(questionData);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchSingleQuestion();
  }, [id]); // Re-run the fetch if the ID changes

  // Handle loading/error states
  if (loading) return <div>Loading question...</div>;
  if (error) return <div>Oops! {error}</div>;
  if (!question) return <div>Question not found</div>;

  // Render the single question
  return (
    <div className="question-show">
      <h2>{question.title}</h2>
      <p>{question.content}</p>
      {/* Add any other fields from your Question model here, like options or answers */}
    </div>
  );
}

export default QuestionShow;

Finally, add links in your list view so users can navigate to individual questions. Use React Router's Link component to avoid full page reloads.

// src/components/QuestionList.js
import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';

function QuestionList() {
  const [questions, setQuestions] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchQuestions = async () => {
      try {
        const response = await fetch('http://localhost:3000/questions');
        if (!response.ok) throw new Error('Failed to load questions');
        
        const questionData = await response.json();
        setQuestions(questionData);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchQuestions();
  }, []);

  if (loading) return <div>Loading questions...</div>;
  if (error) return <div>Oops! {error}</div>;

  return (
    <div className="question-list">
      <h1>All Questions</h1>
      <ul>
        {questions.map(question => (
          <li key={question.id}>
            <Link to={`/questions/${question.id}`}>{question.title}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default QuestionList;

Quick Note on CORS

If your React app is running on a different port (like 3001) than your Rails API (3000), you'll need to enable CORS in Rails:

  1. Add gem 'rack-cors' to your Gemfile, then run bundle install.
  2. Update config/initializers/cors.rb:
    Rails.application.config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'http://localhost:3001' # Replace with your React port
        resource '*',
          headers: :any,
          methods: [:get, :post, :put, :patch, :delete, :options, :head]
      end
    end
    
  3. Restart your Rails server.

That's it! Now when you visit localhost:3000/questions (or the root path), you'll see the list of questions, and clicking any link will take you to localhost:3000/questions/:id where you'll see just that single question.

内容的提问来源于stack exchange,提问作者poppashingles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:27:50