React + Styled Components: каждый рендер setState сбрасывает все компоненты

Я наткнулся на поразительную тайну с React + Styled Components. Я в полной растерянности.

Вот мой компонент:

import React from 'react';
import styled from "styled-components";

class SearchBar extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            searchStr: '',
            isEditing: false,
            isSearching: false,
            isIdle: true,
            activeMode: 'search'
        };
    }

    onChange=(e)=>{
        console.info("on change input");
        this.setState( {
            ...this.state
        }, () => {
            // nada...
        });
    };


    render () {

        const SearchBarStyle = styled.div`
            height: 85%;
            `;

        return (
            <SearchBarStyle>
                <input type = "text" onChange = {this.onChange} placeholder = "Search"/>
            </SearchBarStyle>
        );
    }
}


export default SearchBar;

Проблема в следующем: как только я начинаю вводить input, вызывается setState. Когда это происходит, все под <SearchBarStyle> сбрасывается! мой первый введенный символ стирается, и элемент управления вводом начинается с нуля, показывая подсказку-заполнитель...

А вот и умопомрачительные вещи:

Если я заменю <SearchBarStyle> на простой divИЛИ Я никогда не звоню setState проблема не возникает. Я могу свободно печатать... Каким-то образом вызов setState для компонента, созданного с помощью styled-components, полностью сбрасывает его!

Виски-Танго-Фокстрот!?

я вижу проблему в setState, где вы просто снова устанавливаете состояние в старое состояние. Здесь нет ничего плохого в styled-components

Vishal Rajole 19.06.2019 05:28

Это не проблема. Компонент был упрощен для Stackoverflow. Почему мой <input> стирается каждый раз при вводе в поле ввода? (который вызывает setState и сбрасывает все? и почему замена <SearchBarStyle> на простой div решает проблему?

JasonGenX 19.06.2019 05:30

Это не имеет ничего общего со стилем-компонентом. Пожалуйста, удалите тег styled-components

konekoya 19.06.2019 05:33

удален тег styled-components

JasonGenX 19.06.2019 05:42
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
4
685
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Проверьте этот код

Выпуск №1. Входное значение не установлено. Входной элемент должен быть

<input
          value = {this.state.searchStr}
          type = "text"
          onChange = {this.onChange}
          placeholder = "Search"
        />

Выпуск №2. целевое входное значение не установлено в состоянии, ваш обработчик onChange должен быть

onChange = e => {
    this.setState({ searchStr: e.target.value });
  };

https://codesandbox.io/s/heuristic-montalcini-mkiyq

Это сработало, спасибо, но теперь есть другая проблема. Каждое нажатие клавиши при обновлении на <input> вызывает потерю фокуса... Мне нужно повторно щелкнуть ввод, чтобы восстановить его.

JasonGenX 19.06.2019 05:37

это из-за того, что стилизованный компонент определен не в том месте. Обновлен код песочницы. Теперь фокус не теряется.

Vishal Rajole 19.06.2019 05:40

Вы не используете значение state в качестве значения input и не присваиваете новое значение элементам с state по e.target.value.

onChange = (e) => {
  console.info("on change input");
  // e.target.value contains the updated value of the input
  this.setState({
    searchStr: e.target.value
  }, () => {
    console.info('state updated', this.state);
  });
};

Назначьте searchStr из state значению

<input
  type = "text"
  value = {this.state.searchStr}
  onChange = {this.onChange}
  placeholder = "Search"
/>

Чтобы сохранить фокус ввода, определите SearchBarStyles над внешней частью компонента SearchBar.

const SearchBarStyle = styled.div`
  height: 85%;
`;


class SearchBar extends React.Component {
  ..

Это сработало, спасибо! но теперь есть другая проблема. Каждое нажатие клавиши при правильном обновлении <input> вызывает потерю фокуса... Мне нужно повторно щелкнуть ввод, чтобы снова ввести его

JasonGenX 19.06.2019 05:38
Ответ принят как подходящий
  1. Объявите SearchBarStyle над классом. Объявление его в render() будет повторно отображать компонент каждый раз, когда у вас будет обновление в компоненте SearchBar.
import React from "react";
import styled from "styled-components";

const SearchBarStyle = styled.div`
  height: 85%;
`;

class SearchBar extends React.Component {
...
  1. Неверный способ обновления состояния. Так должно быть:
onChange = e => {
  console.info("on change input")
  this.setState({
    searchStr: e.target.value
  }, () => {

  });
};
  1. Назначьте значение состояния в поле ввода.
  <input type = "text" onChange = {this.onChange} value = {this.state.searchStr} placeholder = "Search"/>

Это правильно и полно, потеря фокуса вызвана этим

Avin Kavish 19.06.2019 05:40

ты прав! фокус действительно теряется из-за этого. перемещение его за пределы класса решает проблему с фокусом!

JasonGenX 19.06.2019 05:41

Я обновил свой ответ и разъяснил ошибки в опубликованном коде.

Ken Labso 19.06.2019 05:41

Здесь вы используете Uncontrolled Components, поэтому каждый setState ваш компонент подвергается повторному рендерингу, и в конечном итоге вы теряете старое значение.

Чтобы решить эту проблему, вы должны использовать Controlled Components, т.е. установить для атрибута ввода value значение состояния, например,

<input type = "text" onChange = {this.onChange} placeholder = "Search" value = {this.state.searchStr} />

Это сработало, спасибо! но теперь есть другая проблема. Каждое нажатие клавиши при правильном обновлении <input> вызывает потерю фокуса... Мне нужно повторно щелкнуть ввод, чтобы снова ввести его

JasonGenX 19.06.2019 05:40

Другие вопросы по теме