React-Bootstrap 面包屑抛出无效挂钩调用错误
React-Bootstrap Breadcrumbs throwing invalid hook call error
我曾尝试在我的测试项目中使用 Bootstrap 面包屑,但经常遇到错误。我刚刚将页面从组件 class 重写为函数,但仍然出现相同的错误。
我遇到的可怕错误:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
React 2
useBootstrapPrefix ThemeProvider.js:29
Breadcrumb Breadcrumb.js:20
React 12
unstable_runWithPriority scheduler.development.js:468
React 2
workLoop scheduler.development.js:417
flushWork scheduler.development.js:390
performWorkUntilDeadline scheduler.development.js:157
js scheduler.development.js:180
js scheduler.development.js:645
factory react refresh:6
Webpack 20
react.development.js:1476
The above error occurred in the <Breadcrumb> component:
../../node_modules/react-bootstrap/esm/Breadcrumb.js/Breadcrumb<@http://localhost:3000/static/js/vendors-node_modules_react-bootstrap_esm_Breadcrumb_js.chunk.js:1162:7
Breadcrumbs
div
div
div
EditStudentBS@http://localhost:3000/static/js/src_pages_EditStudentBS_js.chunk.js:36:74
Suspense
Routes@http://localhost:3000/static/js/bundle.js:35775:7
Router@http://localhost:3000/static/js/bundle.js:35712:7
BrowserRouter@http://localhost:3000/static/js/bundle.js:35189:7
App
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
源代码 - link 中的完整项目
https://codesandbox.io/s/unruffled-galois-n7pps
import React, { useState, useEffect } from 'react';
import { Link, useParams } from 'react-router-dom';
import axios from 'axios';
import { Breadcrumb } from 'react-bootstrap';
const EditStudentBS = () => {
let props = useParams();
const [name, setName] = useState('');
const [course, setCourse] = useState('');
const [email, setEmail] = useState('');
const [phone, setPhone] = useState('');
const [isLoading, setIsLoading] = useState(true);
// Handle the changes of the form fields into state
let HandleInput = (e) => {
switch (e.target.name) {
case 'name':
setName(e.target.value);
break;
case 'course':
setCourse(e.target.value);
break;
case 'email':
setEmail(e.target.value);
break;
case 'phone':
setPhone(e.target.value);
break;
default:
return null;
}
};
useEffect(() => {
console.log(props);
const FetchData = async (StudentID) => {
const Resp = await axios.get(
`http://localhost/api/edit-student/${StudentID}`
);
if (Resp.data.status === '200') {
setName(Resp.data.student.name);
setCourse(Resp.data.student.course);
setEmail(Resp.data.student.email);
setPhone(Resp.data.student.phone);
setIsLoading(false);
}
};
const StudentID = props.id;
FetchData(StudentID);
// console.log(StudentID, this.props);
}, [props]);
// Update student function, posts via AXIOS to the Laravel backend
let UpdateStudent = async (e) => {
e.preventDefault();
const StudentID = this.props.params.id;
setIsLoading(true);
const Resp = await axios.put(
`http://localhost/api/update-student/${StudentID}`,
this.state
);
setIsLoading(false);
if (Resp.data.status === '200') {
console.log(Resp.data.message);
}
};
const Breadcrumbs = () => {
return (
<Breadcrumb>
<Breadcrumb.Item>Students</Breadcrumb.Item>
<Breadcrumb.Item active>Edit Students</Breadcrumb.Item>
</Breadcrumb>
);
};
return (
<div className="container">
<div className="row">
<div className="col-md-12">
<Breadcrumbs />
</div>
</div>
<div className="row">
<div className="col-md-6">
<div className="card">
<div className="card-header">
<h4>
Edit Student - {name}
<Link
to={'/'}
className="btn btn-primary btn-sm float-end"
>
Back
</Link>
</h4>
</div>
<div className="card-body">
{isLoading ? (
<h2>Loading...</h2>
) : (
<form onSubmit={UpdateStudent}>
<div className="form-group mb-3">
<label>Student Name</label>
<input
type="text"
name="name"
value={name}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<label>Student Course</label>
<input
type="text"
name="course"
value={course}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<label>Student Email</label>
<input
type="text"
name="email"
value={email}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<label>Student Phone</label>
<input
type="text"
name="phone"
value={phone}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<button
type="submit"
className="btn btn-primary"
>
Update
</button>
</div>
</form>
)}
</div>
</div>
</div>
</div>
</div>
);
};
export default EditStudentBS;
原来你的 code/project 缺少 react-bootstrap
包。它没有列在您链接的 codesandbox 的 package.json
文件中,必须手动添加到那里。
要在本地为您的项目添加,运行 从项目目录:
npm i -s react-bootstrap
这会将 react-bootstrap
和 add/save 的当前版本安装到 package.json
依赖项部分。
我曾尝试在我的测试项目中使用 Bootstrap 面包屑,但经常遇到错误。我刚刚将页面从组件 class 重写为函数,但仍然出现相同的错误。
我遇到的可怕错误:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
React 2
useBootstrapPrefix ThemeProvider.js:29
Breadcrumb Breadcrumb.js:20
React 12
unstable_runWithPriority scheduler.development.js:468
React 2
workLoop scheduler.development.js:417
flushWork scheduler.development.js:390
performWorkUntilDeadline scheduler.development.js:157
js scheduler.development.js:180
js scheduler.development.js:645
factory react refresh:6
Webpack 20
react.development.js:1476
The above error occurred in the <Breadcrumb> component:
../../node_modules/react-bootstrap/esm/Breadcrumb.js/Breadcrumb<@http://localhost:3000/static/js/vendors-node_modules_react-bootstrap_esm_Breadcrumb_js.chunk.js:1162:7
Breadcrumbs
div
div
div
EditStudentBS@http://localhost:3000/static/js/src_pages_EditStudentBS_js.chunk.js:36:74
Suspense
Routes@http://localhost:3000/static/js/bundle.js:35775:7
Router@http://localhost:3000/static/js/bundle.js:35712:7
BrowserRouter@http://localhost:3000/static/js/bundle.js:35189:7
App
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
源代码 - link 中的完整项目 https://codesandbox.io/s/unruffled-galois-n7pps
import React, { useState, useEffect } from 'react';
import { Link, useParams } from 'react-router-dom';
import axios from 'axios';
import { Breadcrumb } from 'react-bootstrap';
const EditStudentBS = () => {
let props = useParams();
const [name, setName] = useState('');
const [course, setCourse] = useState('');
const [email, setEmail] = useState('');
const [phone, setPhone] = useState('');
const [isLoading, setIsLoading] = useState(true);
// Handle the changes of the form fields into state
let HandleInput = (e) => {
switch (e.target.name) {
case 'name':
setName(e.target.value);
break;
case 'course':
setCourse(e.target.value);
break;
case 'email':
setEmail(e.target.value);
break;
case 'phone':
setPhone(e.target.value);
break;
default:
return null;
}
};
useEffect(() => {
console.log(props);
const FetchData = async (StudentID) => {
const Resp = await axios.get(
`http://localhost/api/edit-student/${StudentID}`
);
if (Resp.data.status === '200') {
setName(Resp.data.student.name);
setCourse(Resp.data.student.course);
setEmail(Resp.data.student.email);
setPhone(Resp.data.student.phone);
setIsLoading(false);
}
};
const StudentID = props.id;
FetchData(StudentID);
// console.log(StudentID, this.props);
}, [props]);
// Update student function, posts via AXIOS to the Laravel backend
let UpdateStudent = async (e) => {
e.preventDefault();
const StudentID = this.props.params.id;
setIsLoading(true);
const Resp = await axios.put(
`http://localhost/api/update-student/${StudentID}`,
this.state
);
setIsLoading(false);
if (Resp.data.status === '200') {
console.log(Resp.data.message);
}
};
const Breadcrumbs = () => {
return (
<Breadcrumb>
<Breadcrumb.Item>Students</Breadcrumb.Item>
<Breadcrumb.Item active>Edit Students</Breadcrumb.Item>
</Breadcrumb>
);
};
return (
<div className="container">
<div className="row">
<div className="col-md-12">
<Breadcrumbs />
</div>
</div>
<div className="row">
<div className="col-md-6">
<div className="card">
<div className="card-header">
<h4>
Edit Student - {name}
<Link
to={'/'}
className="btn btn-primary btn-sm float-end"
>
Back
</Link>
</h4>
</div>
<div className="card-body">
{isLoading ? (
<h2>Loading...</h2>
) : (
<form onSubmit={UpdateStudent}>
<div className="form-group mb-3">
<label>Student Name</label>
<input
type="text"
name="name"
value={name}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<label>Student Course</label>
<input
type="text"
name="course"
value={course}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<label>Student Email</label>
<input
type="text"
name="email"
value={email}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<label>Student Phone</label>
<input
type="text"
name="phone"
value={phone}
onChange={HandleInput}
className="form-control"
/>
</div>
<div className="form-group mb-3">
<button
type="submit"
className="btn btn-primary"
>
Update
</button>
</div>
</form>
)}
</div>
</div>
</div>
</div>
</div>
);
};
export default EditStudentBS;
原来你的 code/project 缺少 react-bootstrap
包。它没有列在您链接的 codesandbox 的 package.json
文件中,必须手动添加到那里。
要在本地为您的项目添加,运行 从项目目录:
npm i -s react-bootstrap
这会将 react-bootstrap
和 add/save 的当前版本安装到 package.json
依赖项部分。