开发者问题收集

在 React 中实现多选下拉菜单

2023-02-22
258

我正在尝试使用 React MultiSelect 下拉组件来实现一个下拉框,其中包含将从 API 中检索的选项列表。

我已经复制了启动的代码,安装了 npm 包并将其添加到一个函数中,但我一直收到错误。这是我的代码:

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;

以及我尝试使用它的地方:

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;

但是,当我运行此代码时,我收到以下错误:

Uncaught TypeError:无法在 Checkbox (Checkbox.js:7:1) 处设置未定义的属性(设置“状态”)

我不确定为什么会发生这种情况,因为我使用以下行设置状态:

    this.state = {
        options: [{ name: 'Option 1️', id: 1 }, { name: 'Option 2️', id: 2 }]
    };

虽然这最终会改变,以便我从 API 中获取这些选项而不是对它们进行硬编码,但我现在只是想让包正常工作。有人可以建议我应该怎么做才能解决这个问题吗?

3个回答

您不能在功能组件中使用 “this” 关键字。在功能组件中使用 React hooks。

阅读更多内容

功能组件

React hooks

Hamza Mushtaq
2023-02-22

第一:你对选项进行硬编码,可以正确渲染,你可以查看此代码演示及其用法,也许可以帮助你 使用 mulCheckbox ;

第二:当你从 api 获取选项时,在将数据传输到 Checkbox 功能组件时,你应该在初始化时设置选项数据;如何完成这项工作?你可以使用 Effect,用法如下:

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

希望这可以帮助你,如果你有其他问题,你可以发表评论

Cognia
2023-02-22

问题是您尝试像在类组件中一样设置状态,但您使用的是函数式组件(对于简单的事情您应该这样做)。您从 React 导入了 useState() ,但从未调用过它。

此外,选项列表不应存储在状态中,而应为不可变常量(除非出于某种原因它们需要是动态的)。而是在您的常量库中或 Checkbox 组件文件顶部将它们声明为常量。

最后,如果您将状态保留在组件文件中,则无法将其带到应用程序的更大上下文中。我假设这个组件将在具有其他输入组件的表单的更大上下文中调用?您可能希望为整个输入表单创建一个状态或缩减器,然后将状态和设置操作传递给复选框组件。

修改后的复选框组件:

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;

下面是如何在外部上下文中使用的例子:

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>
    )
}
Designly
2023-02-22