
在 React 开发中,当遇到 TypeError: [函数名] is not a function 这类错误时,通常意味着在某个组件内部尝试调用一个期望是函数的值,但该值实际上是 undefined、null 或其他非函数类型。对于 setBodyPart is not a function,这表明在 BodyPart 组件中,它接收到的 setBodyPart prop 并非一个有效的函数。
根据提供的代码片段:
// Home.js (假设是主文件)
const Home = () => {
const [exercises, setExercises] = useState([]);
const [bodyPart, setBodyPart] = useState("all");
return (
<Box>
<HeroBanner />
<SearchExercises
setExercises={setExercises}
bodyPart={bodyPart}
setBodyPart={setBodyPart} // setBodyPart 在此被传递给 SearchExercises
/>
<Exercises
setExercises={setExercises}
exercises={exercises}
bodyPart={bodyPart}
/>
</Box>
);
};
// BodyPart.js (假设是另一个文件)
const BodyPart = ({ item, setBodyPart, bodyPart }) => { // BodyPart 期望接收 setBodyPart
return (
<Stack
onClick={() => {
setBodyPart(item); // 在此调用 setBodyPart
window.scrollTo({ top: 1800, left: 100, behavior: "smooth" });
}}
>
{/* ... */}
</Stack>
);
};错误发生的原因通常有以下几种:
问题的关键在于确保 setBodyPart 作为一个函数,能够从声明它的组件(Home)正确地逐层传递到需要调用它的组件(BodyPart)。
最直接且能有效避免此类 TypeError 的方法,是将所有强关联的组件及其状态逻辑都放置在同一个文件中。这种做法消除了跨文件导入/导出和多层级 prop 传递可能引入的复杂性,使得状态更新函数始终在可访问的作用域内。
优点:
缺点:
示例代码:
将 BodyPart 和 SearchExercises (如果它内部渲染 BodyPart)的定义都移动到 Home.js 文件中:
// Home.js
import React, { useState } from 'react';
import { Box, Stack } from '@mui/material'; // 假设的UI组件库
// import HeroBanner from './HeroBanner'; // 假设 HeroBanner 仍是独立组件
// import Exercises from './Exercises'; // 假设 Exercises 仍是独立组件
// BodyPart 组件定义 (移至 Home.js 内部或其上方)
const BodyPart = ({ item, setBodyPart, bodyPart }) => {
return (
<Stack
// ... 样式和布局
onClick={() => {
setBodyPart(item); // setBodyPart 在此直接可用
window.scrollTo({ top: 1800, left: 100, behavior: "smooth" });
}}
>
{/* ... 其他内容,例如 item 的显示 */}
<div>{item}</div>
</Stack>
);
};
// SearchExercises 组件定义 (如果它内部使用了 BodyPart,也移至 Home.js 内部或其上方)
const SearchExercises = ({ setExercises, bodyPart, setBodyPart }) => {
// 假设 SearchExercises 内部会渲染 BodyPart 列表
const bodyPartsList = ["all", "back", "cardio"]; // 示例数据
return (
<div>
<h2>搜索练习</h2>
{/* 搜索输入框等 */}
<Box sx={{ display: 'flex', overflowX: 'auto', mt: 2 }}>
{bodyPartsList.map((item) => (
<BodyPart
key={item}
item={item}
setBodyPart={setBodyPart} // 从 Home 传递给 SearchExercises 后,再传递给 BodyPart
bodyPart={bodyPart}
/>
))}
</Box>
</div>
);
};
const Home = () => {
const [exercises, setExercises] = useState([]);
const [bodyPart, setBodyPart] = useState("all");
return (
<Box>
{/* <HeroBanner /> */}
<SearchExercises
setExercises={setExercises}
bodyPart={bodyPart}
setBodyPart={setBodyPart}
/>
{/* <Exercises
setExercises={setExercises}
exercises={exercises}
bodyPart={bodyPart}
/> */}
</Box>
);
};
export default Home;第二种方法是保持组件的模块化,将它们放在不同的文件中,但建议将相关联的组件放置在同一个文件夹内。这种组织方式有助于清晰地管理项目结构,并且在实践中,它往往伴随着更规范的导入/导出和 prop 传递机制,从而间接解决了 TypeError 问题。
关键在于:
优点:
注意事项:
示例代码:
假设 Home.js、SearchExercises.js 和 BodyPart.js 都位于同一个文件夹(例如 src/components)下。
// src/components/Home.js
import React, { useState } from 'react';
import { Box } from '@mui/material';
import SearchExercises from './SearchExercises'; // 正确导入同文件夹下的组件
import Exercises from './Exercises'; // 假设 Exercises 也是同文件夹下的组件
// import HeroBanner from './HeroBanner';
const Home = () => {
const [exercises, setExercises] = useState([]);
const [bodyPart, setBodyPart] = useState("all");
return (
<Box>
{/* <HeroBanner /> */}
<SearchExercises
setExercises={setExercises}
bodyPart={bodyPart}
setBodyPart={setBodyPart} // 将 setBodyPart 传递给 SearchExercises
/>
<Exercises
setExercises={setExercises}
exercises={exercises}
bodyPart={bodyPart}
/>
</Box>
);
};
export default Home;
// src/components/SearchExercises.js
import React from 'react';
import { Box } from '@mui/material';
import BodyPart from './BodyPart'; // 正确导入同文件夹下的 BodyPart
// SearchExercises 必须接收并向下传递 setBodyPart
const SearchExercises = ({ setExercises, bodyPart, setBodyPart }) => {
const bodyPartsList = ["all", "back", "cardio"]; // 示例数据
return (
<div>
<h2>搜索练习</h2>
<Box sx={{ display: 'flex', overflowX: 'auto', mt: 2 }}>
{bodyPartsList.map((item) => (
<BodyPart
key={item}
item={item}
setBodyPart={setBodyPart} // 将 setBodyPart 再次传递给 BodyPart
bodyPart={bodyPart}
/>
))}
</Box>
</div>
);
};
export default SearchExercises;
// src/components/BodyPart.js
import React from 'react';
import { Stack } from '@mui/material';
// BodyPart 必须接收 setBodyPart 作为 prop
const BodyPart = ({ item, setBodyPart, bodyPart }) => {
// 最佳实践:在调用前进行类型检查,以提前发现问题
if (typeof setBodyPart !== 'function') {
console.error('Error: setBodyPart prop received by BodyPart is not a function.', setBodyPart);
// 可以选择返回 null 或抛出错误,取决于错误处理策略
return null;
}
return (
<Stack
// ... 样式和布局
onClick={() => {
setBodyPart(item); // 在此安全地调用 setBodyPart
window.scrollTo({ top: 180以上就是React 组件间状态更新函数传递的 TypeError 解析与文件组织策略的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号