React-bootstrap - 无效的钩子调用 - ButtonDropdown
React-bootstrap - Invalid hook call - ButtonDropdown
我是 React 和 JS 的新手,正在尝试为我的 CRUD SpringBoot 应用程序实现 React 前端。我正在尝试将 ButtonDropdown 添加到我的其中一个页面。
代码如下:
通用 buttondrop.js
import React, { Component, useState } from 'react';
import { ButtonDropdown, DropdownMenu, DropdownItem, DropdownToggle } from 'reactstrap';
import Dropdown from 'react-bootstrap/Dropdown';
import DropdownButton from 'react-bootstrap/DropdownButton';
const Bdrop = (props) => {
const [dropdownOpen, setOpen] = useState(false);
const toggle = () => setOpen(!dropdownOpen);
return (
<ButtonDropdown isOpen={dropdownOpen} toggle={toggle}>
<DropdownToggle caret>
Button Dropdown
</DropdownToggle>
<DropdownMenu>
<Dropdown.Item href="#/action-1">Action</Dropdown.Item>
<Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
</DropdownMenu>
</ButtonDropdown>
);
}
App.js
import React, { Component } from 'react';
import './App.css';
import Home from './Home';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import CustomerList from './CustomerList';
import EmployeeList from './EmployeeList';
import CustomerEdit from './CustomerEdit';
import EmployeeEdit from './EmployeeEdit';
import SessionList from './SessionList';
import Bdrop from './buttondrop';
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route path='/' exact={true} component={Home}/>
<Route path='/customers' exact={true} component={CustomerList}/>
<Route path='/customer/:id' component={CustomerEdit}/>
<Route path='/employees' exact={true} component={EmployeeList}/>
<Route path='/employee/:id' component={EmployeeEdit}/>
<Route path='/sessions' exact={true} component={SessionList}/>
<Route path='/buttondrop' component={() => <Bdrop /> }/>
</Switch>
</Router>
)
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
CustomerList.js
import React, { Component, useState } from 'react';
import { Button, ButtonGroup, Container, Table} from 'reactstrap';
import { ButtonDropdown, DropdownMenu, DropdownItem, DropdownToggle } from 'reactstrap';
import Dropdown from 'react-bootstrap/Dropdown';
import DropdownButton from 'react-bootstrap/DropdownButton'
import AppNavbar from './AppNavbar';
import { Link } from 'react-router-dom';
import Bdrop from './buttondrop';
class CustomerList extends Component {
constructor(props) {
super(props);
this.state = {
customers: [],
isLoading: true
};
this.remove = this.remove.bind(this);
}
componentDidMount() {
this.setState({isLoading: true});
fetch('/api/customers')
.then(response => response.json())
.then(data => this.setState({customers: data, isLoading: false}))
}
async remove(id) {
await fetch(`/api/customer/${id}`, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
}).then(() => {
let updatedCustomers = [...this.state.customers].filter(i => i.customer_id !== id);
this.setState({customers: updatedCustomers});
});
}
render() {
const {customers, isLoading} = this.state;
if(isLoading) {
return<p> Loading...</p>;
}
const customerList = customers.map(customer => {
return <tr key={customer.customer_id}>
<td style={{whiteSpace: 'nowrap'}}>{customer.customer_id}</td>
<td>{customer.first_name}</td>
<td>{customer.last_name}</td>
<td>{customer.phone_number}</td>
<td>
<ButtonGroup>
<Button size="sm" color="primary" tag={Link} to={"/customer/" + customer.customer_id}>Edit</Button>
<Button size="sm" color="danger" onClick={() => this.remove(customer.customer_id)}>Delete</Button>
</ButtonGroup>
</td>
</tr>
});
return (
<div>
<AppNavbar/>
<Container fluid>
<div className="float-right">
<Button color="success" tag={Link} to="customer/new">Add Customer</Button>
</div>
<h3>Customers</h3>
{ /* <Bdrop/> */ }
<Table className="mt-4">
<thead>
<tr>
<th width="15%">Customer ID</th>
<th width="20%">First Name</th>
<th width="20%">Last Name</th>
<th width="20%">Phone Number</th>
<th width="10%">Actions</th>
</tr>
</thead>
<tbody>
{customerList}
</tbody>
</Table>
</Container>
</div>
);
}
}
export default CustomerList;
Home.js
import React, { Component } from 'react';
import './App.css';
import AppNavbar from './AppNavbar';
import { Link } from 'react-router-dom';
import { Button, Container } from 'reactstrap';
import { ButtonDropdown, DropdownMenu, DropdownItem, DropdownToggle } from 'reactstrap';
import Dropdown from 'react-bootstrap/Dropdown';
import DropdownButton from 'react-bootstrap/DropdownButton'
class Home extends Component {
render() {
return (
<div>
<AppNavbar/>
<Container fluid>
<h3>Welcome to GMusicAcademy Manager</h3>
</Container>
<Container fluid>
<Button color="link"><Link to="/customers">Manage GMusicAcademy Customers</Link></Button>
<Button color="link"><Link to="/employees">Manage GMusicAcademy Employees</Link></Button>
<Button color="link"><Link to="/sessions">Manage GMusicAcademy Sessions</Link></Button>
<Button color="link"><Link to="/buttondrop">Manage GMusicAcademy ButtonDropDown</Link></Button>
</Container>
</div>
);
}
}
export default Home;
这里的目标是将Bdrop添加到CustomerList中(代码中注释掉了):
<h3>Customers</h3>
<Bdrop/>
<Table className="mt-4">
这会导致“无效挂钩调用错误”。我的react和react-dom是同一个版本,所以不是那个。
为了尝试帮助解决这个问题,我决定尝试创建一个到 Bdrop 的路由,看看我是否能让它正常工作,但这也没有奏效。我尝试过不同的事情,例如:
<Route path='/buttondrop' component={() => <Bdrop /> }/>
或
<Route path='/buttondrop' render={() => <Bdrop /> }/>
这也会导致“无效挂钩错误”。
我试过了
<Route path='/buttondrop'> <Bdrop /> </Route>
这会导致“React.Children.only 预计会收到一个 React 元素子元素”错误。
请帮忙!理想情况下,我想了解这两个问题。
这是一个 sandbox link 到具有工作 <Bdrop />
组件的版本。
不知道您正在使用的 Bootstrap、react-bootstrap 和 reactstrap 的版本,很难说这是否是导致您出现问题的原因。
我是 React 和 JS 的新手,正在尝试为我的 CRUD SpringBoot 应用程序实现 React 前端。我正在尝试将 ButtonDropdown 添加到我的其中一个页面。
代码如下:
通用 buttondrop.js
import React, { Component, useState } from 'react';
import { ButtonDropdown, DropdownMenu, DropdownItem, DropdownToggle } from 'reactstrap';
import Dropdown from 'react-bootstrap/Dropdown';
import DropdownButton from 'react-bootstrap/DropdownButton';
const Bdrop = (props) => {
const [dropdownOpen, setOpen] = useState(false);
const toggle = () => setOpen(!dropdownOpen);
return (
<ButtonDropdown isOpen={dropdownOpen} toggle={toggle}>
<DropdownToggle caret>
Button Dropdown
</DropdownToggle>
<DropdownMenu>
<Dropdown.Item href="#/action-1">Action</Dropdown.Item>
<Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
</DropdownMenu>
</ButtonDropdown>
);
}
App.js
import React, { Component } from 'react';
import './App.css';
import Home from './Home';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import CustomerList from './CustomerList';
import EmployeeList from './EmployeeList';
import CustomerEdit from './CustomerEdit';
import EmployeeEdit from './EmployeeEdit';
import SessionList from './SessionList';
import Bdrop from './buttondrop';
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route path='/' exact={true} component={Home}/>
<Route path='/customers' exact={true} component={CustomerList}/>
<Route path='/customer/:id' component={CustomerEdit}/>
<Route path='/employees' exact={true} component={EmployeeList}/>
<Route path='/employee/:id' component={EmployeeEdit}/>
<Route path='/sessions' exact={true} component={SessionList}/>
<Route path='/buttondrop' component={() => <Bdrop /> }/>
</Switch>
</Router>
)
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
CustomerList.js
import React, { Component, useState } from 'react';
import { Button, ButtonGroup, Container, Table} from 'reactstrap';
import { ButtonDropdown, DropdownMenu, DropdownItem, DropdownToggle } from 'reactstrap';
import Dropdown from 'react-bootstrap/Dropdown';
import DropdownButton from 'react-bootstrap/DropdownButton'
import AppNavbar from './AppNavbar';
import { Link } from 'react-router-dom';
import Bdrop from './buttondrop';
class CustomerList extends Component {
constructor(props) {
super(props);
this.state = {
customers: [],
isLoading: true
};
this.remove = this.remove.bind(this);
}
componentDidMount() {
this.setState({isLoading: true});
fetch('/api/customers')
.then(response => response.json())
.then(data => this.setState({customers: data, isLoading: false}))
}
async remove(id) {
await fetch(`/api/customer/${id}`, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
}).then(() => {
let updatedCustomers = [...this.state.customers].filter(i => i.customer_id !== id);
this.setState({customers: updatedCustomers});
});
}
render() {
const {customers, isLoading} = this.state;
if(isLoading) {
return<p> Loading...</p>;
}
const customerList = customers.map(customer => {
return <tr key={customer.customer_id}>
<td style={{whiteSpace: 'nowrap'}}>{customer.customer_id}</td>
<td>{customer.first_name}</td>
<td>{customer.last_name}</td>
<td>{customer.phone_number}</td>
<td>
<ButtonGroup>
<Button size="sm" color="primary" tag={Link} to={"/customer/" + customer.customer_id}>Edit</Button>
<Button size="sm" color="danger" onClick={() => this.remove(customer.customer_id)}>Delete</Button>
</ButtonGroup>
</td>
</tr>
});
return (
<div>
<AppNavbar/>
<Container fluid>
<div className="float-right">
<Button color="success" tag={Link} to="customer/new">Add Customer</Button>
</div>
<h3>Customers</h3>
{ /* <Bdrop/> */ }
<Table className="mt-4">
<thead>
<tr>
<th width="15%">Customer ID</th>
<th width="20%">First Name</th>
<th width="20%">Last Name</th>
<th width="20%">Phone Number</th>
<th width="10%">Actions</th>
</tr>
</thead>
<tbody>
{customerList}
</tbody>
</Table>
</Container>
</div>
);
}
}
export default CustomerList;
Home.js
import React, { Component } from 'react';
import './App.css';
import AppNavbar from './AppNavbar';
import { Link } from 'react-router-dom';
import { Button, Container } from 'reactstrap';
import { ButtonDropdown, DropdownMenu, DropdownItem, DropdownToggle } from 'reactstrap';
import Dropdown from 'react-bootstrap/Dropdown';
import DropdownButton from 'react-bootstrap/DropdownButton'
class Home extends Component {
render() {
return (
<div>
<AppNavbar/>
<Container fluid>
<h3>Welcome to GMusicAcademy Manager</h3>
</Container>
<Container fluid>
<Button color="link"><Link to="/customers">Manage GMusicAcademy Customers</Link></Button>
<Button color="link"><Link to="/employees">Manage GMusicAcademy Employees</Link></Button>
<Button color="link"><Link to="/sessions">Manage GMusicAcademy Sessions</Link></Button>
<Button color="link"><Link to="/buttondrop">Manage GMusicAcademy ButtonDropDown</Link></Button>
</Container>
</div>
);
}
}
export default Home;
这里的目标是将Bdrop添加到CustomerList中(代码中注释掉了):
<h3>Customers</h3>
<Bdrop/>
<Table className="mt-4">
这会导致“无效挂钩调用错误”。我的react和react-dom是同一个版本,所以不是那个。
为了尝试帮助解决这个问题,我决定尝试创建一个到 Bdrop 的路由,看看我是否能让它正常工作,但这也没有奏效。我尝试过不同的事情,例如:
<Route path='/buttondrop' component={() => <Bdrop /> }/>
或
<Route path='/buttondrop' render={() => <Bdrop /> }/>
这也会导致“无效挂钩错误”。
我试过了
<Route path='/buttondrop'> <Bdrop /> </Route>
这会导致“React.Children.only 预计会收到一个 React 元素子元素”错误。
请帮忙!理想情况下,我想了解这两个问题。
这是一个 sandbox link 到具有工作 <Bdrop />
组件的版本。
不知道您正在使用的 Bootstrap、react-bootstrap 和 reactstrap 的版本,很难说这是否是导致您出现问题的原因。