Условный оператор не учитывает изменения условия
У меня есть React компонент, представляющий форму с инпутами (Текст, Числа, Дата). В инпуте даты есть значение по умолчанию - сегодня(today). Я использую один этот компонент для двух функций: создания объекта и для редактирования объекта. В первом случае все инпуты по умолчанию пустые, кроме инпута даты, в него предаётся значения today. Во втором случае, инпуты получают значение по умолчанию из опциональных пропсов(values), которые поступают в компонент из стейта родительского компонента. Компонент рендериться на странице в двух экземплярах, в один values передаются, в другой нет.
Поскольку наличие values опционально, я включил в дефолтные значения каждого импута условный оператор. В случае с импутом даты он выглядит так:
defaultValue={inputValues?.date ? inputValues.date : today}
В остальных случаях, вместо today ставится пустая строка ''.
Я ожидал, что при изменении стейта, компонент будет ререндериться и вставлять в дефолт инпута, значения values.
На практике же, так происходит только с теми инпутами, которые по умолчанию пустые, а инпут с датой, всегда имеет значение today.
Через консоль я вижу, что при рендере компонента inputValue имеет значение undefiend (useState стоит с пустыми скобками), поэтому я по началу предположил, что values не успевают появится к моменту рендера. Однако при нажатии на кнопку редактирования, корректные values высвечиваются в консоли.
В моём понимании в этот момент, компонент должен ререндериться и подставить значение values, в соответствии с выражением {inputValues?.date ? inputValues.date : today}
Однако по факту, значение календарая = today, а значение всех остальных импутов = values. Если же в выражении заменить today на пустую строку, то при вызове функции редактирования, значение календаря в форме редактирования = inputValues.date, однако дефолтное значение в форме создания теперь пустое, т.к. today в этом случае не задан.
Такое поведение не исключительно для календаря, любой другой инпут ведёт себя таким же образом, если в выражении, заменить пустую строку на любое значение. Буду очень рад, если объясните такое поведение и как его исправить.
Тестовый пример
import React, { useState } from 'react';
export default function Parent() {
const [values, setValues] = useState();
const change = () => setValues({ name: 'name', date: '2023-11-28' });
return (
<Child values={values} change={change} />
);
}
function Child({ values, change }) {
console.log(values);
return (
<div className="container">
<button type="button" onClick={change} >clickMe</button>
<input type="text" defaultValue={values?.name ? values.name : ''} />
<input type="date" defaultValue={values?.date ? values.date : '2023-11-20'} />
</div>
);
}
Ответы (1 шт):
Действительно - defaultValue ведет себя довольно странно.
Я пошарился по интернету - с такой проблемой столкнулся не только ты. В итоге предлагают вот такое "решение" проблемы. Нужно "проблемному" инпуту дать атрибут key, да такой, чтобы он менялся каждый раз при рендере. Т.о. элемент начинает реагировать на изменение стейта в его defaultValue.
//
function App() {
const [values, setValues] = React.useState();
const change = () => setValues({ name: 'name', date: '2023-11-28' });
return (
<Child values={values} change={change} />
);
}
//
function Child({ values = {}, change }) {
console.log(values);
const v1 = values.name ? values.name : ''
const v2 = values.date ? values.date : '2023-11-20'
const k = v2 ? v2 : (new Date()).toString()
return (
<div className="container">
<button type="button" onClick={change} >clickMe</button>
<input type="text" defaultValue={v1} />
<input key={k} type="date" defaultValue={v2} />
</div>
);
}
const domContainer = document.querySelector('#like_button_container');
const root = ReactDOM.createRoot(domContainer);
root.render(<App />);
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<div id="like_button_container"></div>