После этот вопрос я хотел бы заменить компонент TextField (для ввода возраста) на использование компонента Select, поскольку я заметил, что оба имеют свойство inputProps.
Оригинальное приложение:
function App() {
const [state, setState] = React.useState({
cats: [{ name: "cat1", age: "2" }, { name: "cat2", age: "5" }],
owner: "Owner's Name"
});
const handleFormChange = e => {
if (["name", "age"].includes(e.target.dataset.fieldType)) {
const newCats = [...state.cats];
newCats[e.target.dataset.id][e.target.dataset.fieldType] = e.target.value;
setState({ ...state, cats: newCats });
} else {
setState({ ...state, [e.target.name]: e.target.value });
}
};
return (
<form onChange = {handleFormChange}>
<TextField label = "Owner" value = {state.owner} name = "owner" />
<br />
<br />
<TextField
label = "Name 1"
value = {state.cats[0].name}
inputProps = {{ "data-id": 0, "data-field-type": "name" }}
/>
<TextField <-----------------------replace with a Select
label = "Age 1"
value = {state.cats[0].age}
inputProps = {{ "data-id": 0, "data-field-type": "age" }}
/>
</form>
);
}
Компонент Select я заменяю вторым TextField:
<Select
onChange = {handleSelectChange}
label = {"Age 1"}
value = {state.cats[0].age}
inputProps = {{
"data-id": idx,
"data-field-type": "age",
name: "customName"
}}
>
<MenuItem value = {10}>Ten</MenuItem>
<MenuItem value = {20}>Twenty</MenuItem>
<MenuItem value = {30}>Thirty</MenuItem>
</Select>
Но в моей функции handleSelectChange:
const handleSelectChange = e => {
console.info("value", e.target.value); //OK
console.info("name", e.target.name); // OK
console.info("dataset", e.target.dataset); //undefined
};
Атрибуты данных, переданные в inputProps, не определены, почему?
Это codeandbox, который я сделал для тестирования этого поведения: https://codesandbox.io/s/dynamic-form-change-handler-with-select-ft4dj





Для Material-UI Select событием, которое запускает onChange, на самом деле является щелчок по MenuItem. Вот немного упрощенная (без учета регистра multiple) версия этот код:
const handleItemClick = child => event => {
update(false, event);
if (onChange) {
const newValue = child.props.value;
event.persist();
event.target = { value: newValue, name };
onChange(event, child);
}
};
Обратите внимание, что цель события явно создается здесь как объект только со свойствами value и name. Первоначальная цель события клика, как правило, бесполезна, поскольку она не будет соответствовать последовательному элементу DOM, представляющему Select, а вместо этого будет некоторым элементом DOM внутри конкретного MenuItem, по которому был выполнен щелчок.
Отвечая на ваш предыдущий вопрос, я избегал начинать дискуссию о том, является ли подход в руководстве хорошим, поскольку я хотел избежать более подробного рассмотрения аспектов, основанных на мнениях; однако этот сценарий вызывает обсуждение. В общем, я думаю, что в React лучше не помещать в DOM лишние вещи, чтобы обработчики событий могли извлечь информацию обратно. Вместо этого просто предоставьте информацию обработчику событий напрямую.
Например, у вас может быть:
const handleSelectChange = (index, fieldType) => e => {
console.info("value", e.target.value);
console.info("name", e.target.name);
console.info("index", index);
console.info("fieldType", fieldType);
};
// then later in the JSX:
<Select
onChange = {handleSelectChange(idx, "age")}
label = {`Cat ${idx + 1} age`}
value = {state.cats[idx].age}
inputProps = {{
name: "customName"
}}
>
<MenuItem value = {10}>Ten</MenuItem>
<MenuItem value = {20}>Twenty</MenuItem>
<MenuItem value = {30}>Thirty</MenuItem>
</Select>
В приведенном выше фрагменте кода индекс и тип поля передаются handleSelectChange, чтобы вернуть обработчик изменений, который знает эту информацию без необходимости быть частью DOM.
Вот модифицированная версия вашей песочницы, в которой работает: https://codesandbox.io/s/dynamic-form-change-handler-with-select-1sihp.
Этот же подход можно использовать и для ввода текста.