skip to Main Content

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


  1. When using functional components, we need to set state variables using the setState hook. What you are trying is initializing state variables using this.state which should be done for class components

    Using setState hook,

    import React, { useState } from 'react';
    import Multiselect from 'multiselect-react-dropdown';
    
    
    function Checkbox() {
    
        const [options, setOptions] = useState([
          {name: 'Option 1', id: 1},
          {name: 'Option 2', id: 2},
        ]);
    
    const [selectedValue, setSelectedValue] = useState(null);
        
        return (
            <Multiselect
                options={options} // Options to display in the dropdown
                selectedValues={selectedValue} // Preselected value to persist in dropdown
                displayValue="name" // Property name to display in the dropdown options
            />
        );
    }
    
    export default Checkbox;
    
    Login or Signup to reply.
  2. You cant use "this" keyword in functional components. Use React hooks in functional components.

    Read more on

    functional components

    React hooks

    Login or Signup to reply.
  3. 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:

    const [options,setOptions]= useState([]);
    Effect(()=>{
    setOptions(props.options);
    },[props.options])
    

    hope this can help you ,if you have other questions, you can comment this

    Login or Signup to reply.
  4. 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:

    import Multiselect from 'multiselect-react-dropdown';
    
    const options = [
        {
            id: 1,
            name: 'Option 1'
        },
        {
            id: 2,
            name: 'Option 2'
        }
    ]
    
    
    function Checkbox({ selectedOptions, setSelectedOptions }) {
        return (
            <Multiselect
                options={options} // Options to display in the dropdown
                selectedValues={selectedOptions} // Preselected value to persist in dropdown
                displayValue="name" // Property name to display in the dropdown options
                onSelect={setSelectedOptions}
                onRemove={setSelectedOptions}
            />
        );
    }
    
    export default Checkbox;
    

    And here’s an example of how to use in the outer context:

    import React, { useState } from 'react'
    
    export default function SomeForm() {
        const [selectedOptions, setSelectedOptions] = useState();
    
        const handleSelectedOptions = (selectedList) => {
            setSelectedOptions(selectedList);
        }
    
        return (
            <Row className="d-flex align-items-center mb-3">
                <Col className="d-flex justify-content-start">
                    <Checkbox selectedOptions={selectedOptions} setSelectedOptions={handleSelectedOptions} />
                </Col>
            </Row>
        )
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search