Мульти-выбор из формы начальной загрузки - React Hooks - PullRequest
3 голосов
/ 07 ноября 2019

У меня есть список продуктов, и я хочу, чтобы пользователь мог выбрать один или несколько из списка.

Если я щелкаю / выбираю продукт в первый раз, console.log показываетправильный результат. Однако, если я нажимаю два или более раз, я получаю сообщение об ошибке:

TypeError: Невозможно прочитать свойство 'value' из null

Iпробовал две разные стратегии, но обе не работают (проверьте функцию addSelectedProducts):

Первое решение

function SearchProductForm() {
    const [selectedProducts, setSelectedProducts] = React.useState([]);

    function handleSubmit(event){
        event.preventDefault();
        }

    function addSelectedProducts(event) {
        console.log(event.target.value)
        setSelectedProducts(oldArray => [...oldArray, event.target.value]);
        console.log(selectedProducts)
    }

        return (
            <div>
                <Form>
                    <Form.Group controlId="exampleForm.ControlSelect2">
                        <Form.Label>Select the product(s) you are interested about:</Form.Label>
                        <Form.Control as="select" multiple onChange={(event) => addSelectedProducts(event)}>
                            <option value="product1">product1</option>
                            <option value="product2">product2</option>
                            <option value="product3">product3</option>
                            <option value="product4">product4</option>
                            <option value="product5">product5</option>
                        </Form.Control>
                    </Form.Group>
                    <Button variant="primary" type="submit" onClick={()=>handleSubmit()}>
                        Submit
                    </Button>
                </Form>
            </div>
        );
    }

export default SearchProductForm;

Второе решение

function SearchProductForm() {
    const [selectedProducts, setSelectedProducts] = React.useState([]);

function handleSubmit(event){
    event.preventDefault();
    }

function addSelectedProducts(event) {
    let options = event.target.options
    for (var i = 0, l = options.length; i < l; i++) {
        if (options[i].selected) {
            setSelectedProducts(oldArray => [...oldArray, event.target.value]);
            console.log(selectedProducts)

        }
    }
}

    return (
        <div>
            <Form>
                <Form.Group controlId="exampleForm.ControlSelect2">
                    <Form.Label>Select the product(s) you are interested about:</Form.Label>
                    <Form.Control as="select" onChange={(event) => addSelectedProducts(event)} multiple>
                        <option value="product1">product1</option>
                        <option value="product2">product2</option>
                        <option value="product3">product3</option>
                        <option value="product4">product4</option>
                        <option value="product5">product5</option>
                    </Form.Control>
                </Form.Group>
                <Button variant="primary" type="submit" onClick={()=>handleSubmit()}>
                    Search
                </Button>
            </Form>
        </div>
    );
}

Ответы [ 3 ]

3 голосов
/ 07 ноября 2019

Рикардо затронул пул событий в своем ответе, но я хочу предложить решение, в котором вам не нужно сохранять событие, для меня это немного вонючий код.

Вы можете захватить все выбранныепараметры, а затем установите их вместо попытки объединить новое состояние со старым.

function addSelectedProducts(event) {
  // Alternative if you need to target ie
  // const selectedOptions = [...event.target.options].filter(o => o.selected).map(o => o.value)

  const selectedOptions = [...event.target.selectedOptions].map(o => o.value)

  setSelectedProducts(selectedOptions)
}

Причина, по которой вы сталкиваетесь с ошибкой выше, заключается в том, что

setSelectedProducts(oldArray => [...oldArray, event.target.value]);

является асинхронными к тому времени, когда обратный вызов вызывается, ваше событие больше не существует. Подробнее здесь: https://reactjs.org/docs/events.html#event-pooling

https://codesandbox.io/s/dank-thunder-12be3

1 голос
/ 07 ноября 2019

Привет, вы проверили документы ? Возможно, вам нужно добавить event.persist(), потому что вы обрабатываете event внутри function.

 function addSelectedProducts(event) {
        event.persist()
        console.log(event.target.value)
        setSelectedProducts(oldArray => [...oldArray, event.target.value]);
        console.log(selectedProducts)
    }

Другое решение может включать установку переменной event.target.value:

 function addSelectedProducts(event) {
        let value = event.target.value;
        console.log(event.target.value)
        setSelectedProducts(oldArray => [...oldArray, event.target.value]);
        console.log(selectedProducts)
    }

0 голосов
/ 07 ноября 2019

Я думаю, вы можете попробовать onChange={addSelectedProducts} вместо onChange={(event) => addSelectedProducts(event)}

...