I am trying to use React MultiSelect Dropdown component to implement a dropdown box with a list of options that will be retrieved from an API.
I have copied the started code, installed the npm package and added it into a function, but I keep getting errors. Here is my code:
import React, { useState } from 'react';
import Multiselect from 'multiselect-react-dropdown';
function Checkbox() {
this.state = {
options: [{ name: 'Option 1️', id: 1 }, { name: 'Option 2️', id: 2 }]
};
return (
<Multiselect
options={this.state.options} // Options to display in the dropdown
selectedValues={this.state.selectedValue} // Preselected value to persist in dropdown
displayValue="name" // Property name to display in the dropdown options
/>
);
}
export default Checkbox;
And where I am trying to use it:
import React, { useState } from 'react';
import { Container, Row, Col, Form } from 'react-bootstrap';
import DateRange from '../DateRange';
import SiteComponentLoader from '../SiteComponentLoader';
import Checkbox from '../Checkbox';
function LotList({ status }) {
status ??= "";
const defaultDateRange = {
from: null, //new Date().toISOString().split('T')[0],
to: null
};
const [dateFilter, setDateFilter] = useState(defaultDateRange);
const [includeGraded, setIncludeGraded] = useState(false);
const [selectedOptions, setSelectedOptions] = useState();
const handleSelectedOptions = (selectedList) => {
setSelectedOptions(selectedList);
}
const handleIncludeGraded = (e) => {
setIncludeGraded(e.target.checked);
}
return (
<Container fluid>
<Row className="d-flex align-items-center mb-3">
<Col className="d-flex justify-content-start">
<DateRange dateFilter={dateFilter} setDateFilter={setDateFilter} />
</Col>
<Row className="d-flex align-items-center mb-3">
<Col className="d-flex justify-content-start">
<Checkbox selectedOptions={selectedOptions} setSelectedOptions={handleSelectedOptions} />
</Col>
</Row>
<Col className="d-flex justify-content-end pt-2">
<Form.Check type="checkbox" onChange={handleIncludeGraded} className="me-2" style={{ marginTop: "-0.5rem" }} />
<Form.Label>Include graded items?</Form.Label>
</Col>
</Row>
<Row>
{/* TODO: Get the site code from configuration in some way */}
<SiteComponentLoader component="./Pages/LotListTable" site="SCP" tableFilters={{ status: status, dateFilter: dateFilter, includeGraded: includeGraded }} />
</Row>
</Container>
);
}
export default LotList;
However, when I run this I get the following errors:
Uncaught TypeError: Cannot set properties of undefined (setting 'state') at Checkbox (Checkbox.js:7:1)
I am not sure why this is happening as I am setting state with the line:
this.state = {
options: [{ name: 'Option 1️', id: 1 }, { name: 'Option 2️', id: 2 }]
};
Although this will eventually change so that I get these options from the API rather then hardcoding them, I am just trying to get the package to work for now. Can anyone recommend what I should do to fix this?
4
Answers
When using functional components, we need to set state variables using the
setState
hook. What you are trying is initializing state variables usingthis.state
which should be done forclass components
Using
setState
hook,You cant use "this" keyword in functional components. Use React hooks in functional components.
Read more on
functional components
React hooks
first: you hardcode the options,can render correct,you can see this code demo and it usage,may be can help you use mulCheckbox;
second: when you get the options from the api ,when transfer the data to the Checkbox function component,you should set the options data when init it; and how to complate the job? you can use Effect,usage like this:
hope this can help you ,if you have other questions, you can comment this
The problem is you’re trying to set the state like you do in a class component, but you are using a functional component (as you should for something simple). You imported
useState()
from React but you never invoked it.Also, the list of options should not be stored in the state, but instead should be immutable constants (unless they need to be dynamic for some reason). Instead declare them as a constant in either your constants library or at the top of the Checkbox component file.
Lastly, if you keep the state in the component file, you’ll have no way of getting it out to the larger context of your app. I would assume this component would be invoked in the larger context of a form with other input components? You would want to create a state or reducer for the enter form as a whole and then pass the state and set action to the Checkbox component.
Modified Checkbox Component:
And here’s an example of how to use in the outer context: