Skip to content

Instantly share code, notes, and snippets.

@kolomeetz
Last active April 16, 2017 18:29
Show Gist options
  • Save kolomeetz/66527b5abfdf2f7fe045ccff916fe823 to your computer and use it in GitHub Desktop.
Save kolomeetz/66527b5abfdf2f7fe045ccff916fe823 to your computer and use it in GitHub Desktop.

Кажется, основное реакт-кунфу — в умении проводить границы между компонентами. Тогда переделывать становится гораздо проще.

Первый слой разделения: это контейнеры и презентационные компоненты (Дэн Абрамов про это написал достаточно подробно). Контейнеры готовят данные, а презентационные компоненты их отображают. С помощью разных контейнеров мы подгружаем/готовим разные наборы данных, а с помощью одного презентационного — отображаем.


Второй слой: все блоки, которые собираются итератором.

Плохо:

render() {
  const list = this.props.people.map(person => (
    <li key={person.id}>
      <Link to={`/person/${person.id}`}>{person.name}</Link>
    </li>
  );

  return (
    <ul>{list}</ul>
  )
}

Хорошо:

render(){
  const list = this.props.people.map(person => <PersonLi person={person} key={person.id} />)

  return (
    <ul>{list}</ul>
  )
}

и PersonLi уже отображает <li> с собственным скоупом. Когда понадобится добавить в такой PersonLi какую-то логику (а понадобится обязательно), внутри скоупа с объектом работать будет во сто крат проще.


Третий слой: выделять компонент, если блоки явно типовой и будет использоваться в других местах приложения. Например, ссылка на человека.

Плохо:

class PersonLi extens React.Component {
  render() {
    const person = this.props.person;

    return (<li><Link to={`/person/${person.id}`}>{person.name}</Link></li>);
  }
}

Хорошо:

class PersonLi extens React.Component {
  render() {
    return (<li><PersonLink person={this.props.person} /></li>);
  }
}

class PersonLink extens React.Component {
  render() {
    const person = this.props.person;

    return (<Link to={`/person/${person.id}`}>{person.name}</Link>);
  }
}

Четвертый: совсем уж атомные блоки, из которых собирается интерфейс, и которые отвязаны от логики приложения: инпуты, например. Такой атомный контролируемый инпут отображает переданное ему значение и возвращает в компонент с формой введенное пользователем значение. Тут же обработка шорткатов, например.

export default class Checkbox extends React.Component {
  constructor(props) {
    super(props);

    this.onChange = this.onChange.bind(this);
  }

  onChange(event){
    this.props.onChange(event.target.name, event.target.checked);
  }

  render() {
    return (
      <label>
        <input
          type="checkbox"
          name={this.props.name}
          checked={this.props.checked}
          onChange={this.onChange}/> {this.props.label}
      </label>
    )
  }
}

И вызов такого компонента в какой-нибудь форме:

class Post extends React.Component {

  constructor(props){
    super(props);
    
    this.state = {
      subscribe: false
    };

    this.updateField = this.updateField.bind(this);
  }

  updateField(name, value){
    this.setState({name: value});
  }
  
  render(){
    return ( 
      <div className="form">
        ...
        <Checkbox 
          label="Subscribe to updates"
          name="subscribe" 
          checked={this.state.subscribe} 
          onChange={this.updateField} />
        ...
      </div>
    )
  }
}

Наверняка есть готовые npm-пакеты с такими блоками :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment