Некоторые фишки React

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

Условный рендеринг

Вместо вот таких записей:

render() {
  if (flag) {
    return <div>
      <Inner />
    </div>
  } else {
    return <div/>
  }
}

всегда можно записать вот так:

render() {
  return <div>
    {flag && <Inner />}
  </div>
}

Массивы элементов

Что только не пишут с массивами:

render() {
  let list = [];
  for (let i = 0; i < this.props.text.length; ++i) {
     list.push(<li key={i}> // key нужен, чтобы отличать элементы массива
       {this.props.text[i]}
     </li>)
  }
  return <ul>
    {list}
  </ul>
}

Есть замечательный новый метод .map()

Посмотрите на аргументы передаваемой функции

render() {
  return <ul>
    {this.props.text.map((item, i) => <li key={i}>{item}</li>)}
  </ul>
}

Массив элементов из метода render

Раздутый JS-код может распространяться дальше и на HTML-разметку. Например, так случилось, что из метода render() нам необходимо вернуть несколько элементов. Часто для этого заводится элемент, в котором располагается массив элементов:

render() {
  return <div class="unnecessary">
    <div class="row1"/>
    <div class="row2"/>
  </div>
}

Вместо этого, можно использовать React.Fragment:

render() {
  return <React.Fragment>
    <div class="row1"/>
    <div class="row2"/>
  </React.Fragment>
}

или совсем сокращённую запись:

render() {
  return <>
    <div class="row1"/>
    <div class="row2"/>
  </>
}

Стрелочные компоненты

Если у вашего компонента вдруг не оказалось внутреннего state и хуков, то вместо

class MyComponent extends React.Component {
  render() {
    return <div>{this.props.text}</div>
  }
}

можно написать стрелочный компонент (!):

const MyComponent = (props) => <div>{props.text}</div>

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

Destructuring

Данная возможность ES6 позволяет немного сократить код. И вместо этого

class MyComponent extends React.Component {
  render() {
    return <div className={this.props.className}>
      {this.props.text}
    </div>
  }
}

можно писать

class MyComponent extends React.Component {
  render() {
    const {className, text} = this.props;
    return <div className={className}>{text}</div>
  }
}

В стрелочных компонентах такое сокращение выглядит более эпично:

const MyComponent = (props) => (
  <div className={props.className}>
    {props.text}
  </div>
);

преобразуется в:

const MyComponent = ({className, text}) => (
  <div className={className}>
    {text}
  </div>
);

Redux, а точнее redux-connect

В большинстве примеров по redux-connect присутствует такая запись:

const mapStateToProps = state => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}
const mapDispatchToProps = dispatch => {
  return {
    onTodoClick: id => {
      dispatch(toggleTodo(id))
    }
  }
}
const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)
export default VisibleTodoList

Эту запись можно смело переписать не только таким образом:

export default connect(
  state => ({  // чтобы arrow возвращала литерал объекта - ставим скобки ()
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }),
  dispatch => ({
    onTodoClick: id => dispatch(toggleTodo(id))
  })
)(TodoList)

Но и вовсе используя декораторы:

@connect(state => ({
  todos: getVisibleTodos(state.todos, state.visibilityFilter)
}), dispatch => ({
    onTodoClick: id => dispatch(toggleTodo(id))
}))
export default class TodoList { // ...

Это, разумеется, только основы, и в программе курса «Разработчик JavaScript» мы разбираем многие другие интересности!

Есть вопрос? Напишите в комментариях!