Задать вопрос
TheSnegok
@TheSnegok

Как вызывать useState в дочерней компоненте и менять state сверху?

Мне нужно чтобы при нажатии на букву она добавлялась в value в инпут в компоненту выше:
основа:
function App() {
	const [value, setValue] = useState('');
	return (
		<div className="App">
			<main>
				<div className="gliph">
					<div className="gliphArea">
						<h1>Gliphs</h1>
						<input className="inputLine" value={value} readOnly />
						<div className="gliphAlphabet">
							<Gliph value={value} set={() => setValue()} />
						</div>
					</div>
				</div>
			</main>
			<div className="history">
				<input type="text" className="inputLine" readOnly />
			</div>
		</div>
	);
}

Дочерний компонент:
const alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];

const Gliph = ({ value, set }) => {
    const handleClick = (letter) => {
        set(value + letter);
    }
    return (
        <>
            {alphabet.map(l => <div key={l} className="gliphMine" onClick={() => handleClick(l)}>{l}</div>)}
        </>
    )
}

Код ошибки:
A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Когда это он стаёт неконтроллируемым?
  • Вопрос задан
  • 527 просмотров
Подписаться 1 Средний 4 комментария
Помогут разобраться в теме Все курсы
  • Яндекс Практикум
    Мидл фронтенд-разработчик
    5 месяцев
    Далее
  • Яндекс Практикум
    React-разработчик
    3 месяца
    Далее
  • Яндекс Практикум
    Фронтенд-разработчик
    10 месяцев
    Далее
Решения вопроса 2
Krasnodar_etc
@Krasnodar_etc
fundraiseup
Замените
set={() => setValue()}

На
set={setValue}

Иначе вы всегда функцию setValue без аргументов вызываете
И вообще старайтесь не делать анонимные функции при передаче пропсов, это удар по оптимизации
Ответ написан
Alexandroppolus
@Alexandroppolus
кодир
Не поленился скопипастить и проверить. Ошибка не выскочила.
Зато слегонаца пооптимизировал (написано на TS, у меня подопытная заготовка на нем):
type Pr = {
  set: React.Dispatch<React.SetStateAction<string>>
}

const Gliph: React.FC<Pr> = React.memo(({ set }) => {
  console.log('render Gliph')
  const handleClick = (letter: string) => {
    set((value) => value + letter)
  }
  return (
    <>
      {alphabet.map((l) => (
        <button type="button" key={l} className="gliphMine" onClick={() => handleClick(l)}>
          {l}
        </button>
      ))}
    </>
  )
})

export const App: React.FC = () => {
  const [value, setValue] = useState('')
  console.log('render App')

  return (
    <div>
      <input className="inputLine" value={value} readOnly />
      <Gliph set={setValue} />
    </div>
  )
}


при таком раскладе не случается перерендер Gliph при изменении значения инпута.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
ITK academy Нижний Новгород
от 80 000 до 120 000 ₽
ITK academy Воронеж
от 50 000 до 90 000 ₽