Свойство переключателя, отмеченное переключателем, не вызывается из кнопки в списке - PullRequest
1 голос
/ 06 ноября 2019

Я хочу написать компонент React, который предоставляет пользователю список предложений, которые он может принять или отклонить с помощью переключателя из Семантический пользовательский интерфейс .

desired component

Мое приложение выглядит следующим образом.

import React from "react";
import "./App.css";
import {Proposals} from "./components/Proposals";

function App() {
    const proposals = [
        {id: "1", context: "The cat is happy."},
        {id: "2", context: "The triangle is blue."}
    ];

    return (
        <div>
            <Proposals proposals={proposals}/>
        </div>
    )
}

export default App;

Компонент «Мои предложения» выглядит следующим образом.

import React, {useState} from "react"
import {Form, Header, List, Radio} from "semantic-ui-react";

export const Proposals = ({proposals}) => {
    const [judgments, setJudgments] = useState(
        proposals.reduce((result, proposal) => {
            result[proposal.id] = {accept: false, reject: false};
            return result;
        }, {})
    );

    const judge = (id) => {
        return function (e, {value}) {
            judgments[id].accept = value === "accept";
            judgments[id].reject = value === "reject";
            setJudgments(judgments)
        };
    };

    return (
        <div id="proposals">
            <Header>Proposals</Header>
            <List>
                {proposals.map(proposal => {
                        return (
                            <List.Item key={proposal.id}>
                                <div>{proposal.context}</div>
                                <Form>
                                    <Form.Group inline>
                                        <Radio label="Accept"
                                               value="accept"
                                               name="accept-reject"
                                               checked={judgments[proposal.id].accept}
                                               onChange={judge(proposal.id)}/>
                                        <Radio label="Reject"
                                               value="reject"
                                               name="accept-reject"
                                               checked={judgments[proposal.id].reject}
                                               onChange={judge(proposal.id)}/>
                                    </Form.Group>
                                </Form>
                            </List.Item>
                        )
                    }
                )}
            </List>
        </div>
    )
};

Сложно написатьмой обработчик onChange judge в качестве закрытия, чтобы я мог передать идентификатор предложения, над которым работали. Это работает. Когда я нажимаю переключатель, вызывается функция judge, и если я записываю ее значения в консоль, все они выглядят корректно.

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

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


Следуя предложению ответа ниже, я изменил свой judgeк следующему.

const judge = (id) => {
    return function (e, {value}) {
        setJudgments(prev => {
            if (prev.id !== id) return prev;
            return {
                ...prev,
                accept: value === "accept",
                reject: value === "reject"
            }
        })
    }
};

У меня та же проблема.

Это, похоже, связано с моим некорректным состоянием обновления , хотя.

1 Ответ

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

Нет ничего плохого в закрытии на judge. Ваша проблема в том, что вы изменяете state

judgments[id].accept = value === "accept"

. Вы должны установить свое состояние, используя версию средства обновления useState.

Как это

return function (e, {value}) {
     setJudgments(prev =>({
         ...prev,
         [id] :{
             ...prev[id],
            accept: value === "accept",
            reject: value === "reject"
         }
     }))
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...