Альтернатива React Tic Tac Toe

Вы прошли официальные крестики-нолики React? руководство? Если да, то вы могли заметить этот текст, выделенный жирным шрифтом во введении.

У вас может возникнуть соблазн пропустить его, потому что вы не создаете игры, но дайте ему шанс.

Я предполагаю, что даже команда React знает, что не так уж интересно создавать игру Tic Tac Toe, поскольку они вставили эту строку. Хотя проект действительно дает вам понимание React, вам понадобится сильная воля, чтобы пройти обучение. .

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

Итак, какие интерфейсные проекты вы можете выбрать, чтобы узнать о React? Когда я просматривал учебные пособия и сообщения в блогах, я заметил, что хорошее вводное руководство по React должно делать следующие вещи:

  • Научите основам React, таким как компоненты, состояние и свойства
  • Обработка динамических данных, изменения состояния и реквизита
  • Показывает использование метода жизненного цикла

Ну, почти все из основные понятия вкладка, правда.

Реагировать на основные концепции

К концу этого руководства вы будете лучше понимать использование таких концепций React, как компоненты, методы состояния и жизненного цикла, а также то, как они используются в обычном пользовательском интерфейсе веб-приложений.

Примечание. Для части CSS этого руководства мы будем использовать Bootstrap, чтобы он выглядел лучше, без написания собственного CSS. Вы можете смело игнорировать className части примера кода, так как они взяты из Bootstrap

Фронтенд-развлечение со списком карт

Давайте начнем с использования JSX, компонентов и реквизита — основных компонентов пользовательского интерфейса React. Вот наш конечный продукт:

Итак, давайте построим его. Все, что нам нужно сделать, это создать <Card/> Компонент, который возвращает элементы JSX:

function Card(props) {
    return (
      <div className="card">
        <img className="card-img-top" 
          src=" 
          alt="cap image" />
          <div className="card-body">
          <h5 className="card-title">Title Placeholder</h5>
          <p className="card-text">Description Placeholder</p>
          <a href="#" className="btn btn-primary">Learn more</a>
        </div>
      </div>
    );
}

А затем создайте родительский компонент, который отображает <Card/> три раза. Мы можем назвать это <CardList/>

function CardList() {
  return (
    <div className="row">
      <div className="col-sm-4">
        <Card />
      </div>
      <div className="col-sm-4">
        <Card />
      </div>
      <div className="col-sm-4">
        <Card />
      </div>
    </div>
  );
}

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

ReactDOM.render(<CardList />, document.getElementById('root'));

Теперь нам нужно включить в эти карты наши собственные данные, так что передайте некоторые props внутрь

function CardList() {
  return (
    <div className="row">
      <div className="col-sm-4">
        <Card
          featureImage="
          title="How To Make Interactive ReactJS Form"
          description="Let's write some interactive form with React"
          link="
        />
      </div>
      <div className="col-sm-4">
        <Card
          // your data
        />
      </div>
      <div className="col-sm-4">
        <Card
          // your data
        />
      </div>
    </div>
  );
}

А затем использовать эти реквизиты в нашем <Card/> составная часть:

function Card(props) {
  return (
    <div className="card">
      <img className="card-img-top" src={props.featureImage} alt="cap image" />
      <div className="card-body">
        <h5 className="card-title">{props.title}</h5>
        <p className="card-text">{props.description}</p>
        <a href={props.link} className="btn btn-primary">Learn more</a>
      </div>
    </div>
  );
}

Теперь это <Card/> компонент использовал JavaScript в своем JSX, очень похожем на механизмы шаблонов, не так ли?

Вы можете задаться вопросом: «Почему мы используем function вместо class для объявления компонента?»

Это потому, что мы не держим state или используйте методы жизненного цикла. Компоненты React объявлены как class чтобы использовать эти две вещи (хотя теперь мы можем сделать это и с хуками React, но пока оставим хуки).

Как видно из примера, пользовательский интерфейс React состоит из трех основных компонентов: компонентов, JSX и реквизита.

  • Составная часть представляет собой единый элемент пользовательского интерфейса, состоящий из методов и JSX.
  • JSX — это HTML, дополненный JS, что позволяет нам описывать пользовательский интерфейс с использованием синтаксиса JavaScript.
  • Реквизит являются произвольными входными данными, которые мы передаем в компонент.

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

Сложности с формой мастера

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

Давайте посмотрим, как вы можете создать подобную форму с помощью React:

Самый простой способ создать многоступенчатую форму — создать элемент формы-контейнера, который содержит внутри себя все компоненты шага мастера. Эта диаграмма поможет вам понять это ясно.

Диаграмма мастера реагирования

Хотя форма кажется более сложной, чем обычная форма, форма мастера по-прежнему использует тот же принцип React. Но так как у нас есть state в этом упражнении нам нужно включить новый принцип:

  • Состояние используется для хранения динамических данных

Вместо одного компонента формы у нас будет один родительский компонент и три дочерних компонента. На приведенной выше диаграмме <MasterForm/> компонент будет отправлять данные и функции дочерним компонентам через реквизиты, а дочерние компоненты будут запускаться handleChange() функция для установки значений в состоянии <MasterForm/> . Нам также понадобится функция для перемещения формы с одного шага на другой.

Так же, как CardList отправить реквизит CardЭти дочерние компоненты получат свойства от <MasterForm/> за value а также onChange реквизит.

  • <Step1/> компонент будет отображать ввод адреса электронной почты
  • <Step2/> отобразит ввод имени пользователя
  • <Step3/> отобразит ввод пароля и кнопку отправки

Родитель <MasterForm/> будет предоставлять как данные, так и функции дочерним компонентам, а дочерние компоненты будут передавать пользовательский ввод обратно родительскому, используя его props.

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

function Step1(props) {
  if (props.currentStep !== 1) {
    return null
  } 
  return(
    <div className="form-group">
      <label htmlFor="email">Email address</label>
      <input
        className="form-control"
        id="email"
        name="email"
        type="text"
        placeholder="Enter email"
        value={props.email}
        onChange={props.handleChange}
        />
    </div>
  )
}

Поскольку дочерние компоненты выглядят почти одинаково друг с другом, я просто показываю один из них выше. Полный код можно посмотреть в демо. Обратите внимание, как мы использовали function вместо classтак как мы не используем state или методы жизненного цикла.

Затем мы можем поместить этот дочерний компонент в основную форму. render() функцию и передать необходимые реквизиты. Для обработки событий, когда пользователь что-то вводит в текст, мы использовали функцию onChange синтетическое событие, которое является частью основных библиотек React для обработки событий. Подробнее здесь.

Давайте сделаем <MasterForm/> компонент и инициализировать его состояние и методы. А currentStep состояние будет инициализировано значением 1. Это используется для индикатора шага, чтобы наша форма знала, на каком шаге мы находимся в данный момент. Мы будем использовать класс ES6, так как для этого компонента требуется локальное состояние:

class MasterForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      currentStep: 1,
      email:  '',
      username: '',
      password: '', 
    }
  }

  

  handleChange = event => {
    const {name, value} = event.target
    this.setState({
      [name]: value
    })    
  }
   
  handleSubmit = event => {
    event.preventDefault()
    const { email, username, password } = this.state
    alert(`Your registration detail: \n 
           Email: ${email} \n 
           Username: ${username} \n
           Password: ${password}`)
  }
  
  
}

Затем мы добавляем шаги в метод рендеринга <MasterForm/> . Он отправит handleChange() функция и требуется state значения в качестве реквизита, обратите внимание на выделенные блоки кода:

render() {    
  return (
    <React.Fragment>
    <h1>A Wizard Form!</h1>
    <p>Step {this.state.currentStep} </p> 
      
    <form onSubmit={this.handleSubmit}>
    {/* 
      render the form steps and pass required props in
    */}

      <Step1 
        currentStep={this.state.currentStep} 
        handleChange={this.handleChange}
        email={this.state.email}
      />
      <Step2 
        currentStep={this.state.currentStep} 
        handleChange={this.handleChange}
        username={this.state.username}
      />
      <Step3 
        currentStep={this.state.currentStep} 
        handleChange={this.handleChange}
        password={this.state.password}
      />       

    </form>
    </React.Fragment>
  )
}

Потому что render() должен возвращать один элемент, <React.Fragment> Компонент позволяет вам возвращать несколько элементов в методе render() без создания дополнительного элемента DOM. Подробнее здесь.

Затем мы добавляем функцию следующего или предыдущего шага, которая будет проверять, есть ли у текущего шага предыдущий или следующий шаг. Если да, то подтолкнет currentStep вверх или вниз:

class MasterForm extends Component {
  

  _next = () => {
    let currentStep = this.state.currentStep
    currentStep = currentStep >= 2? 3: currentStep + 1
    this.setState({
      currentStep: currentStep
    })
  }
    
  _prev = () => {
    let currentStep = this.state.currentStep
    currentStep = currentStep <= 1? 1: currentStep - 1
    this.setState({
      currentStep: currentStep
    })
  }

  

Мы создадим функции, которые будут проверять, является ли текущий шаг 1 или 3. Это потому, что у нас есть трехшаговая форма мастера. Вы можете изменить их, если у вас их больше. Кнопки исчезнут, если нет следующего или предыдущего шага от текущего шага. Эти кнопки вызовут наш _next а также _previous методы.


previousButton(){
  let currentStep = this.state.currentStep;
  if(currentStep !==1){
    return (
      <button 
        className="btn btn-secondary" 
        type="button" onClick={this._prev}>
      Previous
      </button>
    )
  }
  return null;
}

nextButton(){
  let currentStep = this.state.currentStep;
  if(currentStep <3){
    return (
      <button 
        className="btn btn-primary float-right" 
        type="button" onClick={this._next}>
      Next
      </button>        
    )
  }
  return null;
}

Осталось только отобразить наши кнопки «Далее» и «Предыдущий».


render(){
  return(
    <form onSubmit={this.handleSubmit}>
      {/* 
        ... other codes
      */}
      
      {this.previousButton()}
      {this.nextButton()}
    </form>
  )
}

Если вам интересно, почему мы использовали () на вызов кнопок выше, это потому, что нам нужно фактически выполнить функции кнопки. _next а также _previous функции выполняются только при нажатии кнопки, поэтому они не должны иметь () по вызову.

Фу! Здесь много взаимодействий между компонентом и состоянием, но я надеюсь, что теперь вы понимаете, как использовать state в приложении React. Обобщить, state это просто произвольные данные, которые мы определили в компоненте, и они навсегда становятся частью этого компонента. Мы можем передать его другому компоненту, мы можем обновить его, и мы можем делать условные вещи на основе того, что state наш компонент в настоящее время находится в.

В этом образце формы мы использовали состояние для отслеживания ввода пользователя и текущего шага формы мастера. Поскольку React — это односторонний поток данных от родительского к дочернему компоненту, всегда помните, что только владелец state может изменить или обновить его.

Использовать state мы можем использовать ES6 Class или React Hooks (будет объяснено в другом руководстве).

Готовы к еще одному упражнению? Давайте сделаем это тогда!

PS: если вы работаете с формой React, ознакомьтесь с этим подробным руководством от Аринич

Приложение для поиска на GitHub

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

Примечание. Для этого приложения я написал дополнительный CSS. Обязательно посетите вкладку CSS кода выше и вставьте его, если вы не разветвляете ручку.

Во-первых, давайте рассмотрим Github API, который мы собираемся использовать. Поскольку мы ищем только по имени пользователя, нам нужен этот URL-адрес API:


Давайте подготовимся к созданию приложения, сначала написав большой компонент заголовка. На самом деле это просто статический Bootstrap Jumbotron:

const Header = () => {
  return (
    <div className="jumbotron">
      <h1>Github Search App</h1>
      <h2>Search users in GitHub using this simple React application.</h2>
      <p>Click on the card to see more detail about individual user. The search default is nsebhastian (me!)</p>
    </div>
  );
};

Теперь давайте подумаем о создании формы ввода. Нам понадобится:

  1. Форма поиска
  2. Вызов Github API при отправке формы поиска
  3. Отображать результат поиска в виде списка карточек

Начнем с объявления константы API.

const API = 'https://api.github.com/';

Затем давайте инициализируем «верхний» компонент двумя значениями состояния: searchText а также data.

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      searchText: 'nsebhastian',
      data: '',
    }
  }
  
  fetchSearch = username => {
    let url = `${API}search/users?q=${username}`;
    fetch(url)
    .then((res) => res.json() )
    .then((data) => {
      this.setState({
        data: data
      });
    })
    .catch((error) => console.log('Oops! . There Is A Problem' + error) )
  }

  componentDidMount() {
    this.fetchSearch(this.state.searchText);
  }

fetchSearch функция будет извлекать данные из URL-адреса API, преобразовывать их в объект JSON, а затем обновлять наш data состояние со свежевыгруженными данными. Он будет вызываться в методе жизненного цикла компонента. componentDidMount. Если вы не знакомы с методами жизненного цикла, то в основном это методы, запускаемые в определенное время в процессе создания и рендеринга компонентов. Есть и другие способы кроме componentDidMountвключая constructor метод. Не все методы жизненного цикла используются часто, некоторые из них будут использоваться чаще, чем остальные.

Давайте продолжим работу с нашим приложением, написав render метод App составная часть:

render() {
  return (
    <div>
      <MyHeader />
      <SearchForm 
        fetchSearch={this.fetchSearch}
      />
      <Profiles 
        data={this.state.data}
      />
    </div>
  );
}

Вы могли догадаться, увидев код, который нам нужен для создания еще двух компонентов, а именно <SearchForm/> а также <Profiles/>.

Начнем с <SearchForm/>. Мы уже писали форму на React, так что это не составит труда. Нам просто нужен один ввод текста и кнопка отправки. Кроме того, позвольте мне показать вам другой способ получения входного значения без использования state:

class SearchForm extends React.Component {
  render() {
    return (
        <div className="search-bar">
          <form
            className="input-group"
            onSubmit={this.handleForm}>
            <input
              type="search"
              ref="username"
              placeholder="Type Username here"
              className="form-control"/>
            <span className="input-group-btn">
              <button type="submit" className="btn btn-warning">Submit</button>
            </span>
          </form>
        </div>

    )
  }

  handleForm = event => {
    event.preventDefault();
    let username = this.refs.username.value
    this.props.fetchSearch(username);
  }
}

Как видите, мы получаем значение имени пользователя, используя ref. Таким образом, нам не нужно инициализировать state вообще. Мы должны использовать класс ES6 для объявления компонента, так как нам нужно написать handleForm функция.

Теперь пришло время написать последний компонент <Profiles/>. Я воспользуюсь этой возможностью, чтобы показать вам объявление компонента — стиль функции стрелки.

Profiles = props => {
    if(props.data){
      let data = props.data;

      if (data.message === 'Not Found')
        return (
           <div className="notfound">
              <h2>Oops !!!</h2>
              <p>The Component Couldn't Find The You Were Looking For . Try Again </p>
           </div>
        );
        else{
          
          let userList = data.items.map((name) => {
            return (
                <a key={name.id} href={name.html_url} target="blank">
                <div className="bs-callout bs-callout-info">
                  <img className="user" src={name.avatar_url} alt={`${name.login}`}/>
                  <h4>Username : {name.login}</h4>
                  <p> Url : {name.html_url}</p>
                  <p> Score : {name.score} </p>
                </div>
                </a>
            );
          })
          
          return (
            <div>{userList}</div>
          );
        }
    }
    else {
      return <div>Fetching data . . .</div>
    }
}

Если вы следуете этому руководству с самого начала, я думаю, вы можете понять, что это <Profiles/> компонент делаю. Он примет props назвал данные из своего родителя, а затем сделал что-то на основе этого реквизита. Мы использовали map функция для итерации и записи элементов JSX из data множество. Затем он просто возвращается для рендеринга.

Обратите внимание, как key реквизит передается в <a> элемент, чтобы React мог идентифицировать отдельный элемент в списке. Подробнее здесь.

Теперь вы можете выполнить поиск и щелкнуть результат, чтобы перейти в профиль пользователя GitHub. Отличная работа зашла так далеко! На самом деле мы можем улучшить приложение с помощью React Router и создать пользовательскую страницу для подробного просмотра отдельного пользователя, но давайте пока на этом закончим и перейдем к Рефакторинг React Router когда мы на самом деле узнаем о React Router.

Вывод

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

Из этих руководств можно извлечь простые и повторно используемые шаблоны React, которые вы увидите практически в любом приложении React:

  • Составная часть представляет собой единый элемент пользовательского интерфейса, состоящий из методов и JSX.
  • JSX — это HTML, дополненный JS, что позволяет нам описывать пользовательский интерфейс с использованием синтаксиса JavaScript.
  • Реквизит являются произвольными входными данными, которые мы передаем в компонент.
  • Состояние используется для хранения динамических данных. Мы можем использовать его для рендеринга пользовательского интерфейса и хранения полученных данных.
  • Методы жизненного цикла используются для методов, которые необходимо вызывать при рендеринге компонента. Самый простой пример — вызов API и выборка данных.

Так как это было? Разве не веселее изучать React, создавая компоненты, которые вы с большей вероятностью будете использовать в своих проектах? Это слишком сложно для вас? Пожалуйста, дайте мне обратную связь, чтобы я мог улучшить свои навыки письма.

Скоро я расскажу больше о React — например, об использовании Hooks или маршрутизатора React — поэтому, если вам это интересно, обязательно следите за обновлениями, подписавшись на меня или подписавшись на мою рассылку. Обещаю не спамить ваш почтовый ящик!

Спасибо за чтение 😃

Похожие записи

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *