React.js – Тема 6 – Courses WebSkill

Слідкуйте за нами:

Тема 6. React.js Взаємодія з готовим кодом

Завдання 1

Перше завдання зв'язане з грою Хрестики-нулики(Tic-Tac-Toe). Нижче є найпростіший  код гри, у вас буде декілька завдань стосовно змін та удосконалення.

1. Розділімо цей код на компоненти та файли для кожного компонента(Наприклад: Board.js, Game.js, Square.js,calculateWinner.js)
2. Добавте можливість вибору розміру поля ігроком(3х3, 4х4 і тд)
3. Добавити зміну порядку гравців(ходить О або Х), обмеження часу на кожний хід(добавити обмеження на хід 5 секунд, гра стане веселішою)
4.
Стратегічні поради: Виводьте поради, які допоможуть гравцям краще розуміти ситуацію на полі та робити більш інформовані ходи.

App.js
import React from 'react';
import './App.css';

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}

class Board extends React.Component {
  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}
        onClick={() => this.props.onClick(i)}
      />
    );
  }

  render() {
    return (
      <div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      xIsNext: true,
      stepNumber: 0,
    };
  }

  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext,
    });
  }

  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) === 0,
    });
  }

  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

    const moves = history.map((step, move) => {
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        <li key={move}>
          <button onClick={() => this.jumpTo(move)}>{desc}</button>
        </li>
      );
    });

    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>
        <div className="game-info">
          <div>{status}</div>
          <ol>{moves}</ol>
        </div>
      </div>
    );
  }
}

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

export default App;
App.css
body {
    font: 14px 'Arial', sans-serif;
    margin: 20px;
  }
 
  ol {
    padding-left: 20px;
  }
 
  .game {
    display: flex;
    flex-direction: row;
  }
 
  .game-info {
    margin-left: 20px;
  }
 
  .board-row:after {
    clear: both;
    content: '';
    display: table;
  }
 
  .square {
    background: #fff;
    border: 1px solid #999;
    float: left;
    font-size: 24px;
    font-weight: bold;
    line-height: 34px;
    height: 50px;
    margin-right: -1px;
    margin-top: -1px;
    padding: 0;
    text-align: center;
    width: 50px;
  }
 
  .square:focus {
    outline: none;
  }
 
  .board-row {
    margin-bottom: 5px;
  }
 

Завдання 2

Друге завдання зв'язане із сайтом про швидкісні машини.
Нижче будуть файли для уже готового сайту, вам необхідно створити новий додаток і запустити його через термінал/консоль.
Ви раніше використовували такі рішення як кошик товарів, гра на пам'ять, додаток вивчення мов, список справ, вікторина.
Подумайте як можна було б інтегрувати ці системи в цей сайт, і спробуйте це виконати.
Наприклад:
Кошик товарів - можна використати для вибраного сервісу замовлення додаткових послуг або товарів.
Вивчення мов - інтегрувати на сайт, для переключення між різними мовами.
Вікторина(QuizApp) - для швидкого опитування, або підбору контенту по вибору користувача.
Гра на пам'ять(Memory Game) - виконати сторінку призів зі знижками або бонусами, якщо користувачі зіграють в гру.

Виконання усіх завдань не обов'язкове. Поради для виконання:

  1. Анімація: Додавання плавних переходів, ефектів затемнення або зміни розміру для створення привабливих та привабливих ефектів.

  2. Слайдери і галереї: Дозвольте користувачам легко переглядати фотографії або інші візуальні матеріали за допомогою слайдерів або галерей.

  3. Керування станом (State Management): Використовуйте локальний стан компонентів React для оновлення вмісту без перезавантаження сторінки. Наприклад, можна створити форму, яка оновлює вміст в реальному часі під час введення користувачем.

  4. Обробка подій (Event Handling): Реагуйте на події користувача, такі як кліки, подвійні кліки, наведення курсору, інші дії мишею та клавіатурою. Це може бути використано для зміни вмісту, анімацій чи переходів.

  5. Управління життєвим циклом (Lifecycle Management): Використовуйте методи життєвого циклу React, такі як componentDidMount, componentDidUpdate, componentWillUnmount, для виконання певних дій під час монтажу, оновлення чи розмонтажу компонентів.

  6. Умовний рендеринг (Conditional Rendering): Використовуйте умови для визначення, коли і які компоненти мають бути відображені. Наприклад, показувати або ховати певні елементи в залежності від стану даних.

  7. Використання роутингу (Routing): Використовуйте бібліотеку react-router для створення багатосторінкового додатку з використанням шляхів URL.

  8. Форми з контрольованим компонентом (Controlled Components): Створюйте форми, в яких значення елементів форми контролюються компонентами React, що дозволяє легко відстежувати та обробляти зміни.

  9. Передача пропсів (Props Passing): Використовуйте передачу пропсів між батьківськими та дочірніми компонентами для обміну даними та оновлення вмісту компонентів.

  10. Анімація CSS з допомогою React : Використовуйте React для управління класами CSS, що дозволяє змінювати стилі та створювати анімації відповідно до дій користувача.

App.js
import React from 'react';
import Header from './components/Header';
import Footer from './components/Footer';
import Main from './components/Main';
import './App.css';

const App = () => {
  return (
    <div className="App">
      <Header />
      <Main />
      <Footer />
    </div>
  );
};

export default App;
App.css
/* App.css */

/* General styles */
body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
}

/* Header styles */
header {
  background-color: #333;
  color: #fff;
  padding: 10px 0;
  text-align: center;
}

nav ul {
  list-style-type: none;
  padding: 0;
}

nav ul li {
  display: inline;
  margin: 0 10px;
}

nav ul li:hover {
  cursor: pointer;
  text-decoration: underline;
}

/* Footer styles */
footer {
  background-color: #333;
  color: #fff;
  padding: 10px 0;
  text-align: center;
  width: 100%;
}

/* Main styles */
.main {
  padding: 20px;
}

.hero {
  background-image: url('https://img.freepik.com/premium-vector/speed-car-logo-template_160069-12.jpg');
  background-size: contain; /* Змінено на contain для того, щоб зображення вміщалося у контейнер */
  background-position: center;
  background-repeat: no-repeat;
  background-color: black;
  height: 400px;
  display: flex;
  flex-direction: column;
  justify-content: right;
  align-items: center;
  text-align: right;
  color: #fff;
}

.about,
.services,
.contact {
  margin-top: 40px;
  padding: 20px;
}
/* App.css */

.about {
  display: flex;
  justify-content: space-around;
  flex-wrap: wrap;
  padding: 20px;
}

.about p {
  width: 300px;
  padding: 20px;
  margin: 15px;
  text-align: center;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Додаємо тінь */
  transition: transform 0.3s ease-in-out;
}

.about p:hover {
  transform: translateY(-5px); /* Ефект підняття блоку при наведенні */
}

.about h2 {
  font-size: 28px;
  margin-bottom: 20px;
  color: #333;
}

.services {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 20px;
}

.services h2 {
  font-size: 28px;
  margin-bottom: 20px;
  color: #333;
}

.services p {
  color: #555;
  margin-bottom: 15px;
}

.services h3 {
  font-size: 24px;
  margin-bottom: 10px;
  color: #333;
  transition: color 0.3s ease;
}

.services h3:hover {
  color: #f44336; /* Зміна кольору при наведенні */
}

.services p {
  font-size: 16px;
  line-height: 1.6;
  color: #777;
}

/* Анімація для блоків сервісів */
.services {
  display: flex;
  justify-content: space-around;
  flex-wrap: wrap;
  flex-direction: row;
  padding: 20px;
}

.service-block {
  width: 300px;
  padding: 20px;
  margin: 15px;
  text-align: center;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Додаємо тінь */
  transition: transform 0.3s ease-in-out;
}

.service-block:hover {
  transform: translateY(-5px); /* Ефект підняття блоку при наведенні */
}

.service-block h3 {
  font-size: 24px;
  margin-bottom: 10px;
  color: #333;
}

.service-block p {
  font-size: 16px;
  color: #777;
  line-height: 1.6;
}

.services h3:nth-child(odd),
.services p:nth-child(odd) {
  animation: slideInLeft 1s forwards;
}

.services h3:nth-child(even),
.services p:nth-child(even) {
  animation: slideInRight 1s forwards;
}

@keyframes slideInLeft {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideInRight {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.contact {
  background-color: #f9f9f9;
  padding: 20px;
  margin-top: 20px;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  justify-content: center;
  align-items: center;
  text-align: center;
}

.contact h2 {
  font-size: 24px;
  margin-bottom: 15px;
}

.contact form {
  display: flex;
  flex-direction: column;
  width: 300px; /* Налаштуйте ширину форми за вашими потребами */
  margin: 0 auto;
}

.contact label {
  margin-bottom: 5px;
}

.contact input,
.contact textarea {
  padding: 8px;
  margin-bottom: 10px;
  border-radius: 5px;
  border: 1px solid #ccc;
}

.contact button {
  padding: 10px;
  border: none;
  border-radius: 5px;
  background-color: #333;
  color: #fff;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.contact button:hover {
  background-color: #555;
}
Main.js
import React from 'react';

const Main = () => {
  return (
    <main>
      <section className="hero">
        <h1>Welcome to SpeedCar</h1>
        <p>Experience the thrill of speed.</p>
      </section>
      <section className="about">
        <h2>About SpeedCar</h2>
        <p>
          SpeedCar is a leading manufacturer of high-performance sports cars. With a legacy of innovation and cutting-edge technology, we bring you the thrill of speed and precision engineering.
        </p>
        <p>
          Our range of vehicles combines power, elegance, and state-of-the-art design to deliver an unparalleled driving experience.
        </p>
        <p>
          At SpeedCar, we are passionate about pushing the boundaries of automotive excellence and redefining the driving experience.
        </p>
      </section>
      <section className="services">
        <div className="service-block">
          <h3>Performance Tuning</h3>
          <p>Our expert technicians specialize in fine-tuning your vehicle's performance, ensuring optimal speed, handling, and responsiveness on the road or track.</p>
        </div>

        <div className="service-block">
          <h3>Maintenance and Servicing</h3>
          <p>We provide comprehensive maintenance and servicing plans to keep your car in top condition, offering regular inspections, oil changes, and component checks.</p>
        </div>

        <div className="service-block">
          <h3>Customization</h3>
          <p>Personalize your vehicle with our customization options, from unique paint jobs to interior modifications, allowing you to create a one-of-a-kind driving experience.</p>
        </div>

        <div className="service-block">
          <h3>New Service</h3>
          <p>Description of the new service provided by SpeedCar.SpeedCar is a leading manufacturer of high-performance sports cars.</p>
        </div>
      </section>
      <section className="contact">
        <h2>Contact Us</h2>
        <p>Get in touch with us for inquiries and support.</p>
        <form>
          <label>Name:</label>
          <input type="text" placeholder="Your name" />

          <label>Email:</label>
          <input type="email" placeholder="Your email" />

          <label>Message:</label>
          <textarea placeholder="Your message"></textarea>

          <button>Send</button>
        </form>
      </section>
    </main>
   
  );
};

export default Main;
Header.js та Footer.js
// Header.js
import React from 'react';
const Header = () => {
  return (
    <header>
      <nav>
        <ul>
          <li>Home</li>
          <li>About</li>
          <li>Services</li>
          <li>Contact</li>
        </ul>
      </nav>
    </header>
  );
};

export default Header;

// Footer.js
import React from 'react';

const Footer = () => {
  return (
    <footer>
      <p>&copy; 2023 SpeedCar. All rights reserved.</p>
    </footer>
  );
};
export default Footer;
Copyright © 2023 Courses WebSkill | Powered by WebSkill
Scroll to Top