Как перенести реактивность в реакцию с состояниями

kak perenesti reaktivnost v reakcziyu s sostoyaniyami

Это часть моей серии «React для начинающих», посвященная знакомству с React, его основным функциям и лучшим практикам, которых следует придерживаться. Будет больше статей!

< Попередній | Далі >

Если вы знаете, как отобразить компонент React, это прекрасно. Теперь давайте предоставим нашим компонентам свои данные.

Отказ от ответственности: Эта статья посвящена встроенному состоянию React. Обратите внимание, что состояние компонента и Redux несовместимы, поскольку их назначение различно.

На мой взгляд, состояние компонента является специфическим для области компонента (для заполнения формы). Кроме того, состояние Redux помогает делиться одним и тем же состоянием между многими компонентами.

Нужно ли мне государство?

Чтобы изучить состояния, давайте создадим a Question компонент. Он отобразит вопрос да/нет и спросит ответ.

class Question extends React.Component {
  constructor(props) { // Init props and state
      super(props);
      this.state = { answered: false };
      this.answerQuestion = this.answerQuestion.bind(this);
  }
  answerQuestion({target}){ // State update (user answers to the question)
      let answer = target.value === 'true' ? true : false;
      this.setState({ answered: true, answer });
  }
  render() { // Component template in JSX
    if(this.state.answered) {
      return <p>You already answered this question ({this.state.answer ? 'yes' : 'no'})</p>
    }
    return (
      <p>
        <span>{this.props.label}</span>
        <label><input type="radio" name="answer" value="true" onChange={this.answerQuestion}/>Yes</label>
        <label><input type="radio" name="answer" value="false" onChange={this.answerQuestion}/>No</label>
      </p>
    );
  }
}

наш Questionкомпонент содержит только три функции:

  • constructor для инициализации (реквизиты и состояние),
  • answerQuestion это обратный вызов, который запускается, когда пользователь отвечает
  • render что вы, наверное, уже знаете, выводит шаблон компонента.

Этот компонент имеет два разных состояния. На вопрос нет ответа или вопрос имеет ответ.

0*PH4UwIimwdmSGGCS

Реквизиты используются только для метки вопроса, а кроме того, для государства цель гораздо интереснее.

Состояние – это компонент памяти, который запоминает, есть ли ответ на вопросы. Если да, то он тоже знает ответ.

Превратите состояние в пропс

Использовать состояние в компоненте легко. Вы должны инициализировать состояние и вызвать setStateфункционировать, когда вы хотите обновить содержимое.

Представьте себя компонентом. Если состояние изменится, вашей реакцией будет проверить, нужно ли вам обновлять свой дисплей.

Вот как это работает. Реагировать на звонки shouldComponentUpdateперед звонком render (см. документацию). Эта вторая функция создаст следующее состояние Virtual DOM (об этом говорится в последней статье).

class Survey extends React.Component { 
  // Somewhere in constructor function
  this.state = { 
    questions: [ 'Do you like bananas ?', 'Are you a developer ?' ]
  };
  // Somewhere in render function 
  this.state.questions.map(question => <Question label={question}/>)
}

Компоненты получают пропсы других компонентов. Если эти свойства изменятся, компонент будет обновлен.

На самом деле вы уже знаете, как это работает, но возьмем пример a Survey содержит некоторые Question.

The Survey содержит метки вопросов в своем состоянии и передает их Question как собственность.

Когда Survey обновляет свое состояние (звонки setState), то render триггеры функций. Если да, он посылает запрос для Question визуализация (подробности в React doc).

Принять шаблон контейнера

Отделение просмотра от остального кода всегда вызывало большую заботу среди разработчиков. Вот почему большинство шаблонов проектирования, используемых во фреймворках, произошли от шаблона MVC.

Если вы используете React из Redux, вы уже знаете контейнер узор. Фактически это встроенная функция Redux через функцию подключения.

/* 
  Question and QuestionContainer are both regular React components
  QuestionContainer renders a single Question component 
  and provides access to redux stuff through props
*/
const QuestionContainer = 
  connect(mapStateToProps, mapDispatchToProps)(Question);

Пора разделить Question компонент на две составляющие.

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

QuestionContainer будет заниматься государственным управлением.

const Question = (props) => 
  <p>
    <span>{props.label}</span>
    <label><input type="radio" name="answer" value="true" onChange={props.answerQuestion}/>Yes</label>
    <label><input type="radio" name="answer" value="false" onChange={props.answerQuestion}/>No</label>
  </p>
        
class QuestionContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state = { answered: false };
    this.answerQuestion = this.answerQuestion.bind(this);
  }
  answerQuestion({target}){
    let answer = target.value === 'true' ? true : false;
    this.setState({ answered: true, answer });
  }
  render() {
    if(props.answered) {
      return <p>You already answered this question (props.answer ? 'yes' : 'no'})</p>
    }
    // Here is the trick
    return <Question label={this.props.label} answerQuestion={this.answerQuestion}/>
  }
}

Для сравнения с шаблоном проектирования MVC, Question это Просмотреть и QuestionContainer это Контроллер.

Другие необходимые компоненты Questionтеперь буду использовать QuestionContainer вместо Question. Это рассуждение полностью принято в обществе.

Будьте осторожны с антишаблоном setState

Используя это setState является достаточно простым.

Передайте следующее состояние в качестве первого и единственного параметра. Он обновит свойства текущего состояния новыми переданными значениями.

// Very bad pratice: do not use this.state and this.props in setState !
this.setState({ answered: !this.state.answered, answer });

// With quite big states: the tempatation becomes bigger 
// Here keep the current state and add answer property
this.setState({ ...this.state, answer });

Подводя итог, не используйте this.stateи this.propsвнутри setState звонки.

Эти переменные могут иметь не те значения, которые вы ожидаете. React оптимизирует изменения состояния. Он сжимает несколько изменений в одну для проблем производительности (до оптимизации Virtual DOM).

// Note the () notation around the object which makes the JS engine
// evaluate as an expression and not as the arrow function block
this.setState((prevState, props) 
              => ({ ...prevState, answer}));

Вы должны предпочесть другую форму setState. Предоставьте функцию как единственный параметр и используйте prop и state параметры (см. документацию).

Полный компонент опроса

В этой статье мы рассмотрели основные использования состояния в React. Вы можете найти полный код для Survey компонент в следующем Codepen.

Это все было о государствах. Вы сталкивались с компонентами, атрибутами и состояниями, и теперь у вас есть набор для начинающих играть с React.

Надеюсь, вам понравилось прочесть эту статью и вы узнали много нового!

Если вы нашли эту статью полезной, нажмите на ? кнопку несколько раз, чтобы другие нашли статью и выразили вашу поддержку! ?

Не забудьте подписаться на меня, чтобы получать уведомления о моих будущих статьях ?

Это часть моей серии «React для начинающих», посвященная знакомству с React, его основным функциям и лучшим практикам, которых следует придерживаться.

< Попередній | Далі >

➥ JavaScript

➥ Советы и подсказки

Добавить комментарий

Ваш адрес email не будет опубликован.