Как правильно обновить setState нажатием кнопки в ReactJS

Я хочу изменить состояние при нажатии кнопки в React. По сути, я пытаюсь обновить значение имени, отображаемого в моем div, установив this.state.name равным тому, что введено в текстовое поле.

Что я здесь делаю неправильно?

Я также не совсем понимаю разницу между onClick = {() => this.updateText()} и onClick = {this.updateText()} и/или onClick = {this.updateText}. Может, это связано с этим?

Форма.tsx

import React from 'react';

export default class Form extends React.Component<any, any> {

  constructor(props: any) {
    super(props);

    this.state = {
      title: "Enter a new name here",
      description: "Hola",
      textInput: null,
      name: this.props.name
    };
  }

  updateText() {
    this.setState({
      name: this.state.textInput
    });
  }

  render() {
    return (
      <div className = "App">
        <div>{this.props.text} {this.state.name}</div>
        <div>{this.state.age}</div>
        <input type = "text" placeholder = {this.state.title}>{this.state.textInput}</input>
        <br />
        <button type = "submit" onClick = {() => this.updateText()}>Submit</button>
      </div>
    );
  }
}

App.tsx

import React from 'react';
import './App.css';
import Form from "./Form";

class App extends React.Component {
  render() {
    return (
      <div className = "App">
        <Form text = "Hello" age = {22} name = "Thomas"/> 
      </div>
    );
  }
}

export default App;

this.state.name отображается как пустое или нулевое при вводе чего-либо и нажатии кнопки отправки.

Вам нужно добавить обработчик изменений к самому входу. Значение остается нулевым, потому что вы на самом деле не обновляете состояние по мере того, как происходят изменения. reactjs.org/docs/forms.html. Также входы не являются блочными элементами. У них нет детей или эквивалента. Они самозакрывающиеся.

Alexander Staroselsky 02.06.2019 01:23
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как сказал @Alexander Staroselsky в своем комментарии, вы должны использовать обработчик onChange для ввода. Таким образом, вы можете обновить textInput и установить его на свое значение name.

{this.updateText()} не является правильным способом использования обработчика. Если вы используете его таким образом, он вызывается при каждом рендеринге, но не при щелчке.

onClick = {this.updateText} Здесь вы можете использовать ссылку на функцию, и она работает. Но либо вы должны связать его в конструкторе, либо определить его как функцию стрелки. Вы можете увидеть пример ниже.

onClick = {() => this.updateText()} Это вариант его использования. Вы используете здесь функцию стрелки для своего обработчика. Он также работает без привязки функции обработчика для this. Но таким образом ваша функция-обработчик воссоздается при каждом рендеринге. По возможности избегайте этого.

class App extends React.Component {
  render() {
    return (
      <div className = "App">
        <Form text = "Hello" age = {22} name = "Thomas"/> 
      </div>
    );
  }
}

class Form extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      title: "Enter a new name here",
      description: "Hola",
      textInput: "",
      name: this.props.name
    };
  }

  updateText = () => {
    this.setState({
      name: this.state.textInput
    });
  }

  handleChangeEvent = (e) => this.setState({ textInput: e.target.value})

  render() {
    return (
      <div className = "App">
        <div>{this.props.text} {this.state.name}</div>
        <div>{this.state.age}</div>
        <input value = {this.state.textInput} onChange = {this.handleChangeEvent} type = "text" placeholder = {this.state.title} />
        <br />
        <button type = "submit" onClick = {this.updateText}>Submit</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id = "root" />

Это работает! Что мне кажется интересным, так это два разных способа сделать это. На мой взгляд, я предпочитаю следующий подход, который представляет собой небольшое синтаксическое изменение по сравнению с вами. Но, по крайней мере, для меня это кажется немного более кратким. Интересно, производительность такая же?

MisterTams 02.06.2019 02:09

<input type = "text" placeholder = {this.state.title} value = {this.state.textInput} onChange = {(e) => this.handleChangeEvent(e)}/> <br /> <button type= "отправить" onClick = {() => this.updateText()}>Отправить</button>

MisterTams 02.06.2019 02:10

updateText() { this.setState({ name: this.state.textInput, textInput: "" }); } handleChangeEvent(e: any) { this.setState({ textInput: e.target.value}) }

MisterTams 02.06.2019 02:10

@MisterTams, по-вашему, функции обработчика будут воссоздаваться при каждом рендеринге. Вы можете прочитать этот ответ, чтобы увидеть разницу. (Кстати, принятый ответ вводит в заблуждение, вы можете прочитать комментарии). Но для небольших приложений (я имею в виду, если не так много компонентов с такими функциями) производительность будет почти такой же.

devserkan 02.06.2019 03:22

Я все еще не совсем уверен, что понимаю. Значит, ваш фрагмент кода тоже не подходит для этого? Хорошо ли передать обработчик в качестве опоры от родительского к дочернему компоненту? Синтаксис () => смущает меня, потому что я не работаю с React или JavaScript.

MisterTams 02.06.2019 05:02

Мой пример — правильный подход в качестве вашего последнего кода. Использование {() => someFunc()} вызывает воссоздание при каждом рендеринге, поскольку вы используете функцию стрелки в обработчике. Но {someFunc} — это пример использования по ссылке и не вызывает воссоздание. Ваш пример также в порядке, поскольку вы используете функции по их ссылке. Единственная разница между вашим примером и моим заключается в том, что вы используете обычные функции и привязываете их в конструкторе, а я использую стрелочные функции, поэтому не нужно привязывать их для контекста this. Я знаю, здесь разные темы. Но через некоторое время вы поймете разницу.

devserkan 02.06.2019 05:31

Таким образом, в основном мой немного другой подход с использованием функции стрелки в обработчике, таком как onChange = {(e) => this.handleChangeEvent(e)}, вызовет вызов этой функции в любое время, когда что-либо в этом компоненте требует повторного рендеринга. Ваш код в ответе, который я выбрал как принятый, будет давать тот же результат, но не будет автоматически вызывать onChange или onClick каждый раз, когда что-то в этом компоненте требует повторного рендеринга. Поэтому ваш первоначальный ответ имеет тот же эффект, но немного лучше по производительности. Это правильно? Ссылку, которую вы дали, я тоже прочитаю.

MisterTams 02.06.2019 05:39

Не совсем «звонить» или «вызывать», а «отдыхать». Это не влияет на сам компонент, но вызывает ненужный повторный рендеринг дочерних компонентов. Я попытался объяснить это в первой ссылке, которую я дал в своем первом комментарии здесь. Так что кроме слова "вызвать" вы правильно думаете. (Кстати, {someFunc()} вызывает или вызывает функцию немедленно, но обработчики onClick так не работают. Таким образом, вы никогда не используете обработчик таким образом.)

devserkan 02.06.2019 06:04

Потрясающий! Я читал об этом последние несколько минут. Вы здорово помогли! Спасибо!

MisterTams 02.06.2019 06:08

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