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

React向Messages组件传ID对接Flask接口的问题修复

问题描述

我是React开发新手,尝试从Matches.js向Messages.js传递id和user_id,Messages组件需与Flask后端配合使用,但加载时user_id返回undefined。需要修改代码,使id包含在URL中(如http://localhost:5000/messages/6442d4b8e188665ed2268783),同时将user_id(如6442d4b8e188665ed2268784)作为数据发送。

以下是原代码及修改方案:


原代码

Matches.js

import { useState } from "react";
import axios from "axios";
import { useNavigate, useParams } from "react-router-dom";
import "./matches.css";

function Matches() {
  const [userId, setUserId] = useState(""); // userId is the user's id that they enter
  const [matches, setMatches] = useState([]);
  const navigate = useNavigate();
  const { id } = useParams(); // id is the user's id that is passed in from the url

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const res = await axios.get(`http://localhost:5000/matches/${userId}`);
      const matchesWithIds = res.data;
      setMatches(matchesWithIds);
    } catch (error) {
      console.error(error.response.data);
    }
  };

  const handleInputChange = (e) => {
    setUserId(e.target.value);
  };

  const getMessagesWithUser = (matchId) => {
    navigate(`/messages/${userId}`, { state: { id: id, user_id: matchId } });
  };

  return (
    <div>
      <h1>Get Matches</h1>
      <form onSubmit={handleSubmit}>
        <label>
          User ID:
          <input type="text" value={userId} onChange={handleInputChange} />
        </label>
        <button type="submit">Submit</button>
      </form>
      {matches.length > 0 && (
        <div>
          <h2>Matches:</h2>
          <ul>
            {matches.map((match) => (
              <li
                key={match}
                className="match-card"
                onClick={() => getMessagesWithUser(match)}
              >
                {match}
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

export default Matches;

Messages.js

import { useEffect, useState } from "react";
import axios from "axios";
import { useLocation } from "react-router-dom";

function Messages({ id, user_id }) {
  const [messages, setMessages] = useState([]);
  const [messageInput, setMessageInput] = useState("");
  const location = useLocation();
  const userId = location.state.user_id;

  useEffect(() => {
    const getMessages = async () => {
      try {
        const res = await axios.get(`http://localhost:5000/messages/${id}`, {
          params: { user_id: user_id },
        });
        setMessages(res.data);
      } catch (error) {
        console.error(error.response.data);
      }
    };
    getMessages();
  }, [id, user_id]);

  const handleMessageInput = (e) => {
    setMessageInput(e.target.value);
  };

  const sendMessage = async (e) => {
    e.preventDefault();
    try {
      const res = await axios.post(`http://localhost:5000/messages`, {
        sender_id: location.state.id,
        recipient_id: location.state.user_id,
        message: messageInput,
      });
      setMessages((prevMessages) => [...prevMessages, res.data]);
      setMessageInput("");
    } catch (error) {
      console.error(error.response.data);
    }
  };

  return (
    <div>
      <h1>Messages</h1>
      <h2>Conversation with user {user_id}</h2>
      <ul>
        {messages.map((message) => (
          <li key={message._id}>
            {message.sender_id}: {message.message}
          </li>
        ))}
      </ul>
      <form onSubmit={sendMessage}>
        <label>
          Message:
          <input
            type="text"
            value={messageInput}
            onChange={handleMessageInput}
          />
        </label>
        <button type="submit">Send</button>
      </form>
    </div>
  );
}

export default Messages;

App.js

import React, { useState } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Login from "./login/login.js";
import Matches from "./matches.js";
import Home from "./home/home.js";
import Messages from "./messages.js";

function App() {
  const [userId, setUserId] = useState("");

  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login setUserId={setUserId} />} />
        <Route path="/matches" element={<Matches userId={userId} />} />
        <Route path="/home" element={<Home userId={userId} />} />
        <Route path="/messages/:id" element={<Messages />} />
      </Routes>
    </Router>
  );
}

export default App;

Flask后端代码

#get messages with a user
@app.route('/messages/<string:id>', methods=['GET'])
def get_messages_with_user(id):


    required_fields = ["user_id"]
    
    if all(field in request.form for field in required_fields):
        new_user = {
            
            "user_id" : request.form["user_id"]
           
            
        }
   
    
    all_messages = messages_collection.find({
        "$or": [
            {"sender_id": id, "recipient_id": new_user['user_id']},

            {"recipient_id": id, "sender_id": new_user['user_id']},
        ]
    })
    

    message_list = []
    for msg in all_messages:
        # Convert ObjectId fields to strings
        msg['_id'] = str(msg['_id'])
        msg['sender_id'] = str(msg['sender_id'])
        msg['recipient_id'] = str(msg['recipient_id'])
        message_list.append(msg)

    return jsonify(message_list)

修改方案

1. 调整Matches.js的跳转逻辑

将当前用户的id放入URL,匹配用户的user_id通过路由state传递:

import { useState } from "react";
import axios from "axios";
import { useNavigate, useParams } from "react-router-dom";
import "./matches.css";

function Matches() {
  const [userId, setUserId] = useState(""); // 用户输入的ID
  const [matches, setMatches] = useState([]);
  const navigate = useNavigate();
  const { id } = useParams(); // 当前用户的ID,来自URL

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const res = await axios.get(`http://localhost:5000/matches/${userId}`);
      const matchesWithIds = res.data;
      setMatches(matchesWithIds);
    } catch (error) {
      console.error(error.response.data);
    }
  };

  const handleInputChange = (e) => {
    setUserId(e.target.value);
  };

  // 修改跳转:URL携带当前用户id,state传递匹配用户的user_id
  const getMessagesWithUser = (matchId) => {
    navigate(`/messages/${id}`, { state: { user_id: matchId } });
  };

  return (
    <div>
      <h1>获取匹配用户</h1>
      <form onSubmit={handleSubmit}>
        <label>
          用户ID:
          <input type="text" value={userId} onChange={handleInputChange} />
        </label>
        <button type="submit">提交</button>
      </form>
      {matches.length > 0 && (
        <div>
          <h2>匹配用户:</h2>
          <ul>
            {matches.map((match) => (
              <li
                key={match}
                className="match-card"
                onClick={() => getMessagesWithUser(match)}
              >
                {match}
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

export default Matches;

2. 修复Messages.js的参数获取与请求逻辑

使用useParams获取URL中的id,添加空值检查避免undefined:

import { useEffect, useState } from "react";
import axios from "axios";
import { useLocation, useParams } from "react-router-dom";

function Messages() {
  const [messages, setMessages] = useState([]);
  const [messageInput, setMessageInput] = useState("");
  const location = useLocation();
  const { id } = useParams(); // 从URL获取当前用户id
  const userId = location.state?.user_id; // 可选链避免state不存在报错

  useEffect(() => {
    if (!userId) return;
    
    const getMessages = async () => {
      try {
        const res = await axios.get(`http://localhost:5000/messages/${id}`, {
          params: { user_id: userId },
        });
        setMessages(res.data);
      } catch (error) {
        console.error(error.response.data);
      }
    };
    getMessages();
  }, [id, userId]);

  const handleMessageInput = (e) => {
    setMessageInput(e.target.value);
  };

  const sendMessage = async (e) => {
    e.preventDefault();
    if (!userId) return;
    
    try {
      const res = await axios.post(`http://localhost:5000/messages`, {
        sender_id: id,
        recipient_id: userId,
        message: messageInput,
      });
      setMessages((prevMessages) => [...prevMessages, res.data]);
      setMessageInput("");
    } catch (error) {
      console.error(error.response.data);
    }
  };

  return (
    <div>
      <h1>消息</h1>
      <h2>与用户 {userId || "未知"} 的对话</h2>
      <ul>
        {messages.map((message) => (
          <li key={message._id}>
            {message.sender_id}: {message.message}
          </li>
        ))}
      </ul>
      <form onSubmit={sendMessage}>
        <label>
          消息:
          <input
            type="text"
            value={messageInput}
            onChange={handleMessageInput}
          />
        </label>
        <button type="submit" disabled={!userId}>发送</button>
      </form>
    </div>
  );
}

export default Messages;

3. 修正Flask后端的参数获取方式

GET请求使用request.args获取查询参数,添加参数缺失的错误处理:

# 获取与某用户的对话消息
@app.route('/messages/<string:id>', methods=['GET'])
def get_messages_with_user(id):
    user_id = request.args.get('user_id')
    
    # 检查user_id是否存在
    if not user_id:
        return jsonify({"error": "user_id参数缺失"}), 400
   
    all_messages = messages_collection.find({
        "$or": [
            {"sender_id": id, "recipient_id": user_id},
            {"recipient_id": id, "sender_id": user_id},
        ]
    })
    
    message_list = []
    for msg in all_messages:
        # 将ObjectId转换为字符串
        msg['_id'] = str(msg['_id'])
        msg['sender_id'] = str(msg['sender_id'])
        msg['recipient_id'] = str(msg['recipient_id'])
        message_list.append(msg)

    return jsonify(message_list)

修改说明

  • 参数传递:当前用户id通过URL公开传递,匹配用户user_id通过路由state隐式传递,符合需求的URL格式。
  • 错误防护:添加了userId空值检查,避免未定义时发送无效请求或渲染错误内容。
  • 请求规范:GET请求参数通过params传递,后端使用request.args获取,符合HTTP协议规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:37:00