Все статьи по React.js
Добавляем кнопку к нашему приложению. Для этого в файле Articles.js добавили - выделено красным:
import React from 'react' function Article(props) { const {article} = props const body = <section>{ article.text }</section> return( <div> <h2> { article.title } <button onClick={handleClick}>close</button> </h2> { body } <h3> "creation date : "{ (new Date(article.date)).toDateString()} </h3> </div> ); } function handleClick() { console.log('---', 'clicked') } export default Article
Мы добавили кнопку и "проверочную" функция, которая при клике выведет в консоль:
Теперь самое время подумать, как мы будем открывать и закрывать текст статьи этой кнопкой.
В мире реакта мы используем декларативное программирование. То есть мы не описываем что нужно убрать этот текст или напротив - добавить текст в HTML. Мы описываем состояние компонента. И наши объекты могут находиться в различных состояниях. В нашем случае это состояния с открытым и закрытым текстом.
Мы опишем эти состояния, а кнопка будет нам помогать переходить из одного состояния в другое. Именно нажатие на кнопку будет изменять состояние компонента.
Для того, чтобы описывать состояния компонента, нам недостаточно использовать такой простой синтаксис описания компонента в виде функции. Такой синтаксис подходит только для очень простых компонентов, которые имеют небольшую часть логики Stateless компоненты.
Для того, чтобы добавить описание состоянию компонента нам придется использовать второй синтаксис с использование классов ES6:
Для этого нам понадобится базовый компонент реакта - изменяем первую строку "импорта":
import React, {Component} from 'react' class Article extends Component { render() { Cюда весь код функции Article без объявления } }
Единственное что - наши
props
. Для них следует добавить - this.props
, потому как они уже не будут приходить как аргумент, а будут частью компонента - Component
, расширением коего и является наша функция Article
Проверим. Ничего не должно измениться на нашем сайте.
Теперь нам нужно добавить состояние. Для этого внутри компонента мы создадим конструктор в котором зададим начальное состояние
import React, {Component} from 'react' class Article extends Component { // constructor(props) { // super(props) // this.state = { // isOpen: true // } // } state = { isOpen: true } render() { const {article} = this.props console.log('---', this.props) const body = <section>{ article.text }</section> return( <div> <h2> { article.title } <button onClick={handleClick}>close</button> </h2> { body } <h3> "creation date : "{ (new Date(article.date)).toDateString()} </h3> </div> ); } } function handleClick() { console.log('---', 'clicked') } export default Article
Красным цветом мы описали состояние компонента по старому. А ниже, зеленым, описали то же самое, но новым стилем. Поэтому все что красное - можно смело закомментировать. Это совершенно эквивалентные записи просто короткая запись с экспериментальным синтаксисом.
Теперь, нам нужно использовать это состояние. Мы будем его использовать там, где мы создали переменную body и скажем. что если наше состояние активное (
isOpen: true
), то мы будем показывать эту секцию, а нет - значит рендерить пустоту.
Наше состояние храниться в
this.state
. Это специальный атрибут, наподобие this.props
. Ниже написанный код можно выразить так: Если наше состояние isOpen (true)
, то мы показываем секцию, а если нет, то не показываем.
const body = this.state.isOpen && <section>{ article.text }</section>
для эксперимента мы изменим и изначальное состояние на
false
.
Теперь если проверить, то наша статья будет скрыта.
Стоит изменить значение
isOpen:
на true
и статья будет открыта (показана на экране).
Теперь нам осталось сделать так, чтобы изменять состояние.
для смены состояний есть специальный метод ,code>this.set state. Но для того, чтобы работать с контекстом, нам нужно привязать этот контекст к обработчику. существует множество способов как это сделать.
<button onClick={handleClick.bind(this)}>close</button>
Но так делать не стоит.
Мы можем описать этот метод в конструкторе :
import React, {Component} from 'react' class Article extends Component { constructor(props) { super(props) this.state = { isOpen: true } this.handleClick = handleClick.bind(this) } render() { const {article} = this.props console.log('---', this.props) const body = this.state.isOpen && <section>{ article.text }</section> return( <div> <h2> { article.title } <button onClick={this.handleClick}>close</button> </h2> { body } <h3> "creation date : "{ (new Date(article.date)).toDateString()} </h3> </div> ); } handleClick = () =>{ console.log('---', 'clicked') } } export default Article
Красным цветом - это старый развернутый синтаксис. Его можно смело заменить новым - выделен зеленым цветом. Все красное- из кода можно смело удалить!
Во вновь добавленную функцию (зеленым) мы добавили проверочный вывод в консоль. и
this.setState()
в которую мы передали объект у которого мы задаем новое состояние isOpen = true
или isOpen = false
, но мы можем отталкиваться от предыдущего состояния и изменять его - isOpen: !this.state.isOpen
setState()
- операция асинхронная, поэтому там у нас будет старое состояние (!this.state.isOpen
).
Таким образом мы с вами добавили кнопку, которая легко изменяет состояние нашего компонента и показывает или скрывает статью нашего приложения.
Осталось только поменять текст на кнопке -вместо надписи кнопки - "close", мы добавим функцию, которая будет изменять текст в зависимости от состояния:
{this.state.isOpen ? 'close' : 'open'}
Файл Article.js полностью:
import React, {Component} from 'react' class Article extends Component { state = { isOpen: true } render() { const {article} = this.props const body = this.state.isOpen && <section>{ article.text }</section> return( <div> <h2> { article.title } <button onClick={this.handleClick}> {this.state.isOpen ? 'close' : 'open'} </button> </h2> { body } <h3> "creation date : "{ (new Date(article.date)).toDateString()} </h3> </div> ); } handleClick = () =>{ console.log('---', 'clicked') this.setState({ isOpen: !this.state.isOpen }) } } export default Article
Первая часть React
Комментариев нет:
Отправить комментарий