Изменение состояния в React с помощью Onclick

#javascript #reactjs

#javascript #reactjs

Вопрос:

я очень новичок в React, просто хотел создать простую программу с несколькими кнопками, которые соответствуют некоторому значению в state, я хочу, чтобы при нажатии кнопки соответствующее значение отрицалось

 class Parent extends React.Component{
    constructor(props){
        super(props);
        
        this.state={
            a: true,
            b: false,
            c: true,
            d: false
        }
        this.handleAction = this.handleAction.bind(this);
        }
        handleAction(action) {
            this.setState({
                name: !this.state.name

            });

        }
            render(){
                return(
                    <div>
                        <Child onAction={this.handleAction} name='a'/>
                        <Child onAction={this.handleAction} name='b'/>
                        <Child onAction={this.handleAction} name='c'/>
                        <Child onAction={this.handleAction} name='d'/>
                    </div>
                )
            }

    }
    function Child({onAction, name}){
        return (
            <button onClick={onAction}>
             {name}
            </button>
        );
    }
  

есть ли способ сделать это без 4 отдельных функций handleAction? я попытался передать name в onAction , но это выдает Error: Maximum update depth exceeded

я знаю, что должно быть что-то действительно очевидное, чего мне не хватает, спасибо за вашу помощь.

Ответ №1:

Вы могли бы передать name в качестве параметра вашей handleAction функции

 ....
handleAction(name) {
    this.setState( state => ({ [name]: !state[name] }) );
}

render(){
    return(
        <div>
            <Child onAction={() => this.handleAction('a')} name='a'/>
            <Child onAction={() => this.handleAction('b')} name='b'/>
            <Child onAction={() => this.handleAction('c')} name='c'/>
            <Child onAction={() => this.handleAction('d')} name='d'/>
        </div>
    )
}
...
  

Обратите внимание, что чтение this.state изнутри this.setState не является хорошей практикой. смотрите здесь

Комментарии:

1. это работает, спасибо, не могли бы вы, пожалуйста, объяснить причину возврата другой функции, как вы делали раньше handleAction , и другие делали внутри нее вместо прямого изменения состояния, как я сделал?

2. Конечно! причина, по которой не используется this.state непосредственно внутри setState , заключается в том, что setState является асинхронным по своей природе, что означает, что setState это не применяется немедленно. Хотя здесь это маловероятно, существует риск того, что при setState повторном вызове оба они могут найти одно и то же значение в this.state , поскольку setState , возможно, оно еще не было применено. Обновление стиля функции this.setState(state => ...) останавливает чтение устаревших значений из this.state . Вы можете найти подробный пример в документах react

3. извините, возможно, я не совсем ясно выразился, я имел в виду добавленный on ()=> в вашем onAction={() => this.handleAction('a')}

Ответ №2:

Измените обработчик так, чтобы он мог принимать name и возвращать другую функцию.

   handleAction(name) {
    return () => {
      this.setState({
        [name]: !this.state[name],
      });
    };
  }
  

В дочернем компоненте передайте имя этого дочернего компонента

  <Child onAction={this.handleAction("a")} name='a'/>
  

Комментарии:

1. В this.state react docs setState настоятельно не рекомендуется обращаться внутрь

Ответ №3:

Попробуйте это:

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

    this.state = {
      a: true,
      b: false,
      c: true,
      d: false,
    };
    this.handleAction = this.handleAction.bind(this);
  }
  handleAction(name) {
    return () => {
      console.log("name", name);
      this.setState({
        [name]: !this.state[name],
      });
    };
  }
  render() {
    console.log("this.state", this.state);
    return (
      <div>
        <Child onAction={this.handleAction} name="a" />
        <Child onAction={this.handleAction} name="b" />
        <Child onAction={this.handleAction} name="c" />
        <Child onAction={this.handleAction} name="d" />
      </div>
    );
  }
}
function Child({ onAction, name }) {
  return <button onClick={onAction(name)}>{name}</button>;
}
  

Ответ №4:

Как я вижу, вы хотите использовать название кнопки, а затем изменить состояние с тем же именем. Во-первых, вы должны предоставить функции название кнопки. Поскольку событие передается функции по умолчанию, вы можете получить имя, например, таким образом:

 event.target.innerText
  

Затем, если вы используете name в качестве переменной, содержащей значение, вы должны использовать обозначение [name]. В противном случае это добавит свойство ‘name’ к вашему объекту.
В результате ваш обработчик должен выглядеть следующим образом:

 handleAction(e) {
  const name = e.target.innerText
  this.setState({
      [name]: !this.state[name]
  });
}