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

React Hook useParams调用报错求助:非React函数组件或自定义Hook函数中调用useParams

Fixing the "useParams called in non-component/non-Hook function" Error

Let's break down what's going wrong here and how to fix it step by step:

Why the Error Happens

React's Hook rules are strict: Hooks like useParams can only be called at the top level of a React function component or inside a custom Hook (functions starting with use). Your fetchMentors function is a regular helper function, not a component or custom Hook, so calling useParams inside it violates this rule.

Step-by-Step Fixes

1. Move useParams to the Component Top Level

First, extract categoryId at the very top of your MentorList component, so it lives in the component's top scope where Hooks are allowed:

function MentorList() {
  // Pull categoryId at the component's top level
  const { categoryId } = useParams();
  
  // ... rest of your state hooks

2. Update fetchMentors to Use the Top-Level categoryId

Modify your fetchMentors function to reference the already-extracted categoryId instead of trying to call useParams inside it:

const fetchMentors = () => {
  // Now we use the categoryId from the component's top scope
  if (categoryId) {
    console.dir('test');
    Axios.get(`https://localhost:4000/view-by-category/${categoryId}`)
      .then((response) => {
        if (response.data.status === "ok") {
          setMentorsResult(Object.keys(response.data.result));
          setLoading(false);
        } else {
          setError(response.data.error);
          setLoading(false);
        }
      })
      .catch(err => {
        console.dir(err);
        setError("There was an error with the request. Please try again later.");
        setLoading(false);
      });
  }
};

3. Add categoryId to useEffect Dependencies

Since fetchMentors relies on categoryId, we need to include it in the useEffect dependency array. This ensures that when the user navigates to a different category (and categoryId changes), fetchMentors runs again to load the correct set of mentors:

useEffect(() => {
  // ... your fetchCategories and fetchMentors functions
  
  fetchCategories();
  fetchMentors();
}, [categoryId]); // Add categoryId here to trigger re-runs on change

4. Fix the categories Rendering Issue

You're using forEach to generate category links, but forEach doesn't return anything—so your categories variable will be undefined. Replace forEach with map to return a valid array of JSX elements, and add a required key prop for React list rendering:

const categories = categoriesResult.map(item => {
  return <div className="row" key={item.id}>
    <NavLink to={`/mentors/${item.id}`} exact>{item.name}</NavLink>
  </div>;
});

Full Corrected Code

import React, { useState, useEffect } from 'react';
import Axios from "axios";
import {NavLink, useParams} from "react-router-dom";
import Spinner from '../../Spinner';

function MentorList() {
  // Extract categoryId at component top level
  const { categoryId } = useParams();
  
  const [categoriesResult, setCategoriesResult] = useState([]);
  const [mentorsResult, setMentorsResult] = useState([]);
  const [categoriesToId, setCategoriesToId] = useState({});
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    const fetchCategories = () => {
      Axios.get("https://localhost:4000/categories")
        .then((response) => {
          if (response.data.status === "ok") {
            setCategoriesResult(Object.keys(response.data.result));
            setCategoriesToId(response.data.result);
            setLoading(false);
          } else {
            setError(response.data.error);
            setLoading(false);
          }
        })
        .catch(err => {
          console.dir(err);
          setError("There was an error signing you in. Please try again later.");
          setLoading(false);
        });
    };

    const fetchMentors = () => {
      if (categoryId) {
        console.dir('test');
        Axios.get(`https://localhost:4000/view-by-category/${categoryId}`)
          .then((response) => {
            if (response.data.status === "ok") {
              setMentorsResult(Object.keys(response.data.result));
              setLoading(false);
            } else {
              setError(response.data.error);
              setLoading(false);
            }
          })
          .catch(err => {
            console.dir(err);
            setError("There was an error with the request. Please try again later.");
            setLoading(false);
          });
      }
    };

    fetchCategories();
    fetchMentors();
  }, [categoryId]); // Add categoryId to dependencies

  if (loading) {
    return <Spinner />;
  }

  if (error) {
    return <div className="error-message">{error}</div>;
  }

  const mentors = mentorsResult.map(mentor => {
    return <div className="row" key={mentor.id}>
      <p className="mentor-profile-name">{mentor.name}</p>
      <p className="mentor-profile-bio">{mentor.shortBio}</p>
      <NavLink to={`/mentor/${mentor.id}`} exact>View Profile</NavLink>
    </div>
  })

  const categories = categoriesResult.map(item => {
    return <div className="row" key={item.id}>
      <NavLink to={`/mentors/${item.id}`} exact>{item.name}</NavLink>
    </div>;
  });

  return <div className="container">
    <div className="col-3">
      {categories}
    </div>
    <div className="col-9">
      {mentors}
    </div>
  </div>
};

export default MentorList;

Bonus: Improved Error Handling

I added a dedicated render for error messages so users can see when something goes wrong, instead of the app silently failing.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 06:48:37