eFusion 26 августа 2020

πŸ”’ Π”Π΅Π»Π°Π΅ΠΌ ΠΊΠ°Π»ΡŒΠΊΡƒΠ»ΡΡ‚ΠΎΡ€ Π½Π° React c Ρ…ΡƒΠΊΠ°ΠΌΠΈ ΠΈ Context API

ИдСя для ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ дня – собираСм ΠΊΠ°Π»ΡŒΠΊΡƒΠ»ΡΡ‚ΠΎΡ€ Π½Π° React Hooks ΠΈ Context API. ОсваиваСм эти интСрСсныС Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π² Π΄Π΅Π»Π΅. ΠŸΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°.
πŸ”’ Π”Π΅Π»Π°Π΅ΠΌ ΠΊΠ°Π»ΡŒΠΊΡƒΠ»ΡΡ‚ΠΎΡ€ Π½Π° React c Ρ…ΡƒΠΊΠ°ΠΌΠΈ ΠΈ Context API

НС Π±Ρ‹Π²Π°Π΅Ρ‚ Π»ΡƒΡ‡ΡˆΠ΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π² ΠΏΠΎΡ€Ρ‚Ρ„ΠΎΠ»ΠΈΠΎ, Ρ‡Π΅ΠΌ Ρ‚ΠΎΡ‚, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ†Π΅Π½ΠΈΡ‚ΡŒ Π² дСйствии. Π§Π΅Ρ€Π΅Π· Ρ‚Π΅Ρ€Π½ΠΈΠΈ – ΠΊ Π·Π²Ρ‘Π·Π΄Π°ΠΌ! ΠŸΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ простого ΠΊΠ°Π»ΡŒΠΊΡƒΠ»ΡΡ‚ΠΎΡ€Π° Π½Π° React с использованиСм соврСмСнных Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ. ΠŸΡ€ΠΎΠ΅ΠΊΡ‚ ΠΌΠΎΠΆΠ½ΠΎ ΠΈ Π½ΡƒΠΆΠ½ΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠ°Ρ‚ΡŒ. Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ – кликабСльная задСплоСнная Π΄Π΅ΠΌΠΊΠ° (ΠΊΠΎΠ΄ Π½Π° GitHub). НиТС Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ пояснСния ΠΎ Π²Ρ‹Π±Ρ€Π°Π½Π½Ρ‹Ρ… Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΡ….

Π’Π½Π΅ΡˆΠ½ΠΈΠΉ Π²ΠΈΠ΄ ΠΊΠ°Π»ΡŒΠΊΡƒΠ»ΡΡ‚ΠΎΡ€Π°
Π’Π½Π΅ΡˆΠ½ΠΈΠΉ Π²ΠΈΠ΄ ΠΊΠ°Π»ΡŒΠΊΡƒΠ»ΡΡ‚ΠΎΡ€Π°

ΠŸΡ€ΠΈΡΡ‚ΡƒΠΏΠΈΠΌ!

Для Π½Π°Ρ‡Π°Π»Π° запустим стандартный create-react-app:

        npx create-react-app calculator
cd calculator
npm start
    

Ѐайловая структура ΠΈ CSS

Ѐайловая структура рассматриваСмого прилоТСния выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

        src
β”œβ”€β”€ App.js
β”œβ”€β”€ index.js
└── components
    β”œβ”€β”€ BackButton.js
    β”œβ”€β”€ Calculator.js
    β”œβ”€β”€ ClearButton.js
    β”œβ”€β”€ Display.js
    β”œβ”€β”€ EqualButton.js
    β”œβ”€β”€ FunctionButton.js
    β”œβ”€β”€ NegativeButton.js
    β”œβ”€β”€ NumberButton.js
    β”œβ”€β”€ NumberProvider.js
    └── styles
        └── Styles.js
    

Если Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ Ρ‚ΠΎΡ‡Π½ΠΎ ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, Π½ΡƒΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Styled Components для CSS:

        npm -i styled-components
    

Π—Π°Ρ‚Π΅ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Styled CSS Π² Styles.js.

Основная структура

Π€Π°ΠΉΠ» Calculator.js Π·Π°Π΄Π°Π΅Ρ‚ настройки экрана ΠΈ ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Ρ‹. Он содСрТит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄:

Calculator.js
        import React from 'react';
import NumberButton from './NumberButton';
import FunctionButton from './FunctionButton';
import ClearButton from './ClearButton';
import Display from './Display';
import EqualButton from './EqualButton';
import BackButton from './BackButton';
import NegativeButton from './NegativeButton';
import { CalculatorStyles } from './styles/Styles';

const Calculator = () => (
  <CalculatorStyles>
    <div className='display'>
      <h1>CALC-U-LATER</h1>
      <Display />
    </div>
    <div className='number-pad'>
      <ClearButton />
      <BackButton />
      <NegativeButton />
      <FunctionButton buttonValue='/' />
      <NumberButton buttonValue={7} />
      <NumberButton buttonValue={8} />
      <NumberButton buttonValue={9} />
      <FunctionButton buttonValue='*' />
      <NumberButton buttonValue={4} />
      <NumberButton buttonValue={5} />
      <NumberButton buttonValue={6} />
      <FunctionButton buttonValue='-' />
      <NumberButton buttonValue={1} />
      <NumberButton buttonValue={2} />
      <NumberButton buttonValue={3} />
      <FunctionButton buttonValue='+' />
      <div className='zero-button'>
        <NumberButton buttonValue={0} />
      </div>
      <NumberButton buttonValue='.' />
      <EqualButton />
    </div>
  </CalculatorStyles>
);

export default Calculator;
    

ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΊΠ½ΠΎΠΏΠΎΠΊ слСдуСт ΠΎΠ΄Π½ΠΎΠΉ Π±Π°Π·ΠΎΠ²ΠΎΠΉ структурС. НулСвая ΠΊΠ½ΠΎΠΏΠΊΠ° Π»Π΅ΠΆΠΈΡ‚ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΌ div-Π±Π»ΠΎΠΊΠ΅, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ для ΠΌΠ°ΠΊΠ΅Ρ‚Π° Π³Ρ€ΠΈΠ΄.

ΠšΡΡ‚Π°Ρ‚ΠΈ, ΠΎ Π³Ρ€ΠΈΠ΄Π°Ρ…
Если Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΡƒΠ·Π½Π°Ρ‚ΡŒ большС ΠΎ CSS Grid, ΠΌΡ‹ написали нСсколько статСй Π½Π° эту Ρ‚Π΅ΠΌΡƒ.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ свойство buttonValue Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для NumberButton ΠΈ FunctionButton.

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Context API Provider

NumberProvider.js – это сСрдцС прилоТСния ΠΈ мСсто, Π³Π΄Π΅ наши Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΠ±Ρ€Π΅Ρ‚Π°ΡŽΡ‚ Тизнь. Π—Π΄Π΅ΡΡŒ ΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ React Context API – ΠΎΡ‚Π»ΠΈΡ‡Π½Ρ‹ΠΉ инструмСнт ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ‡Π΅Ρ€Π΅Π· Π²Π»ΠΎΠΆΠ΅Π½Π½ΡƒΡŽ структуру ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ Π±Ρ‹ ΠΏΠΎΠΏΠΎΡ‚Π΅Ρ‚ΡŒ. ΠžΠ±Π΅Ρ€Ρ‚ΠΊΠ° ΠΈΠ· ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Π° позволяСт ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π² любой Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ нСзависимо ΠΎΡ‚ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ влоТСнности. Всякий Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, Π½Π°Ρ…ΠΎΠ΄ΡΡ‰ΡƒΡŽΡΡ Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Π°, ΠΎΠ½Π° Π±ΡƒΠ΄Π΅Ρ‚ доступна глобально.

ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ вСрсия NumberProvider.js
        import React from 'react';

export const NumberContext = React.createContext();

const NumberProvider = (props) => {
  const number = '0';
  return (
    <NumberContext.Provider
      value={{
        number,
      }}>
      {props.children}
    </NumberContext.Provider>
  );
};

export default NumberProvider;
    

Π›ΡŽΠ±ΠΎΠ΅ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ доступно всСм Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌ. Π’Π°ΠΊ Ρ‡Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ всё Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ΅ для заполнСния App.js:

App.js
        import React from 'react';
import Calculator from './components/Calculator';
import NumberProvider from './components/NumberProvider';

const App = () => (
  <NumberProvider>
    <Calculator />
  </NumberProvider>
);

export default App;
    

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Context Provider

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΊΠΎΠ΄ для дисплСя. МоТно Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΏΠ΅Ρ€Π΅Π΄Π°Π² Π΅Π³ΠΎ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ useContext ΠΈΠ· Π½ΠΎΠ²ΠΎΠ³ΠΎ React Hooks API. Π‘ΠΎΠ»ΡŒΡˆΠ΅ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠΏ Ρ‡Π΅Ρ€Π΅Π· Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹.

ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ вСрсия Display.js
        import React, { useContext } from 'react';
import { NumberContext } from './NumberProvider';
import { DisplayStyles } from './styles/Styles';

const Display = () => {
  const { number } = useContext(NumberContext);
  return (
    <DisplayStyles>
      <h2>{number}</h2>
      <p>Enter Some Numbers</p>
    </DisplayStyles>
  );
};

export default Display;
    

Число, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ΠΎ Π½Π° Ρ‚Ρ€ΠΈ уровня Π²Ρ‹ΡˆΠ΅ Π² NumberProvider, становится сразу ΠΆΠ΅ доступным ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρƒ Display ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ useContext ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ созданного Π½Π°ΠΌΠΈ NumberContext. Π¦ΠΈΡ„Ρ€ΠΎΠ²ΠΎΠΉ дисплСй Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½, Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ number, исходно ΠΏΡ€ΠΈΡ€Π°Π²Π½Π΅Π½Π½ΠΎΠ΅ Π½ΡƒΠ»ΡŽ.

НачинаСм Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Hooks

Π₯ΡƒΠΊΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Β«ΠΎΠ±Π»Π΅Π³Ρ‡ΠΈΡ‚ΡŒΒ» синтаксис класса ΠΈ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ состояниС Π²Π½ΡƒΡ‚Ρ€ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ². Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ Π² NumberProvider.js, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Ρ…ΡƒΠΊ:

NumberProvider.js
        import React, { useState } from 'react';

export const NumberContext = React.createContext();

const NumberProvider = (props) => {
  const [number, setNumber] = useState('');

  const handleSetDisplayValue = (num) => {
    if (!number.includes('.') || num !== '.') {
      setNumber(`${(number + num).replace(/^0+/, '')}`);
    }
  };

  return (
    <NumberContext.Provider
      value={{
        handleSetDisplayValue,
        number,
      }}>
      {props.children}
    </NumberContext.Provider>
  );
};

export default NumberProvider;
    

ВмСсто написания класса с состояниСм ΠΌΡ‹ Ρ€Π°Π·Π±ΠΈΠ²Π°Π΅ΠΌ состояниС ΠΈ пСрСносим ΠΊΠ°ΠΆΠ΄ΡƒΡŽ Π΅Π³ΠΎ Ρ‡Π°ΡΡ‚ΡŒ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ number. Π—Π΄Π΅ΡΡŒ ΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ setNumber, Π΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ, ΠΊΠ°ΠΊ функция setState. Для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ useState.

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΊΠ½ΠΎΠΏΠΊΠΈ

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Context API Π² любом ΠΈΠ· Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ².

NumberButton.js
        import React, { useContext } from 'react';
import { NumberContext } from './NumberProvider';

const NumberButton = ({ buttonValue }) => {
  const { handleSetDisplayValue } = useContext(NumberContext);
  return (
    <button type='button' onClick={() => handleSetDisplayValue(buttonValue)}>
      {buttonValue}
    </button>
  );
};

export default NumberButton;
    

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°Ρ‡Π°Ρ‚ΡŒ Π²Π²ΠΎΠ΄ΠΈΡ‚ΡŒ значСния, Π·Π°Π΄Π°Π½Π½Ρ‹Π΅ Π² NumberProvider, Π² Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ прилоТСния с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ useContext. БостояниС ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π²Π»ΠΈΡΡŽΡ‰ΠΈΠ΅ Π½Π° Π½ΠΈΡ…, хранятся Π² NumberProvider . ΠŸΡ€ΠΎΡΡ‚ΠΎ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ контСкст – ΠΈ Π³ΠΎΡ‚ΠΎΠ²ΠΎ.

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Π°

Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π½Ρ‹ΠΉ NumberProvider.js находится Π½ΠΈΠΆΠ΅ ΠΈ содСрТит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ вмСстС с Ρ…ΡƒΠΊΠ°ΠΌΠΈ:

  • handleSetDisplayValue: Π·Π°Π΄Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌΠΎΠ΅ Π½Π° дисплСй. ΠœΡ‹ провСряСм, Ρ‡Ρ‚ΠΎ Π² числовой строкС Π΅ΡΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ дСсятичный Π·Π½Π°ΠΊ, ΠΈ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ²Π°Π΅ΠΌ Π΄Π»ΠΈΠ½Ρƒ числа 8 символами. Он ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅Ρ‚ свойство buttonValue Π² NumberButton.js.
  • handleSetStoredValue: ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ строку ΠΈ сохраняСт Π΅Π΅, позволяя ввСсти Π΄Ρ€ΡƒΠ³ΠΎΠ΅ число.
  • handleClearValue: сбрасываСт всё Π² 0. Π­Ρ‚ΠΎ «функция очистки», которая пСрСдаСтся Π² ClearButton.js.
  • handleBackButton: позволяСт ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ Ρ€Π°Π½Π΅Π΅ Π²Π²Π΅Π΄Π΅Π½Π½Ρ‹Π΅ символы ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ, ΠΏΠΎΠΊΠ° Π²Ρ‹ Π½Π΅ Π²Π΅Ρ€Π½Π΅Ρ‚Π΅ΡΡŒ Π² 0. Код привязан ΠΊ BackButton.js.
  • handleSetCalcFunction: срабатываСт ΠΏΡ€ΠΈ Π²Ρ‹Π±ΠΎΡ€Π΅ матСматичСской Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, пСрСдаСтся Π² FunctionButton.js ΠΈ Π² свойства buttonValue.
  • handleToggleNegative: ΠΎΠΏΠ΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅ΠΌΡ‹ΠΌΠΈ ΠΈΠ»ΠΈ сохранСнными значСниями, ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹ΠΌΠΈ Π² NegativeButton.js.
  • doMath: запускаСт Π²Ρ‹Π±Ρ€Π°Π½Π½ΡƒΡŽ ΠΌΠ°Ρ‚Π΅ΠΌΠ°Ρ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ.
NumberProvider.js
        import React, { useState } from 'react';

export const NumberContext = React.createContext();

const NumberProvider = (props) => {
  const [number, setNumber] = useState('');
  const [storedNumber, setStoredNumber] = useState('');
  const [functionType, setFunctionType] = useState('');

  const handleSetDisplayValue = (num) => {
    if ((!number.includes('.') || num !== '.') && number.length < 8) {
      setNumber(`${(number + num).replace(/^0+/, '')}`);
    }
  };

  const handleSetStoredValue = () => {
    setStoredNumber(number);
    setNumber('');
  };

  const handleClearValue = () => {
    setNumber('');
    setStoredNumber('');
    setFunctionType('');
  };

  const handleBackButton = () => {
    if (number !== '') {
      const deletedNumber = number.slice(0, number.length - 1);
      setNumber(deletedNumber);
    }
  };

  const handleSetCalcFunction = (type) => {
    if (number) {
      setFunctionType(type);
      handleSetStoredValue();
    }
    if (storedNumber) {
      setFunctionType(type);
    }
  };

  const handleToggleNegative = () => {
    if (number) {
      if (number > 0) {
        setNumber(`-${number}`);
      } else {
        const positiveNumber = number.slice(1);
        setNumber(positiveNumber);
      }
    } else if (storedNumber > 0) {
      setStoredNumber(`-${storedNumber}`);
    } else {
      const positiveNumber = storedNumber.slice(1);
      setStoredNumber(positiveNumber);
    }
  };

  const doMath = () => {
    if (number && storedNumber) {
      switch (functionType) {
        case '+':
          setStoredNumber(
            `${Math.round(`${(parseFloat(storedNumber) + parseFloat(number)) * 100}`) / 100}`
          );
          break;
        case '-':
          setStoredNumber(
            `${Math.round(`${(parseFloat(storedNumber) - parseFloat(number)) * 1000}`) / 1000}`
          );
          break;
        case '/':
          setStoredNumber(
            `${Math.round(`${(parseFloat(storedNumber) / parseFloat(number)) * 1000}`) / 1000}`
          );
          break;
        case '*':
          setStoredNumber(
            `${Math.round(`${parseFloat(storedNumber) * parseFloat(number) * 1000}`) / 1000}`
          );
          break;
        default:
          break;
      }
      setNumber('');
    }
  };

  return (
    <NumberContext.Provider
      value={{
        doMath,
        functionType,
        handleBackButton,
        handleClearValue,
        handleSetCalcFunction,
        handleSetDisplayValue,
        handleSetStoredValue,
        handleToggleNegative,
        number,
        storedNumber,
        setNumber,
      }}>
      {props.children}
    </NumberContext.Provider>
  );
};

export default NumberProvider;
    

Π˜Ρ‚ΠΎΠ³ΠΎΠ²ΠΎΠ΅ прСдставлСниС экрана

Обновим Ρ„Π°ΠΉΠ» для отобраТСния экрана. Он Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ number ΠΈ storedNumber Π² соотвСтствии с functionType. Π•Ρ‰Π΅ Π΅ΡΡ‚ΡŒ нСсколько ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ 0 ΠΏΡ€ΠΈ вставкС пустой строки вмСсто числа.

Display.js
        import React, { useContext } from 'react';
import { NumberContext } from './NumberProvider';
import { DisplayStyles } from './styles/Styles';

const Display = () => {
  const { number, storedNumber, functionType } = useContext(NumberContext);
  return (
    <DisplayStyles>
      <h2>{!number.length && !storedNumber ? '0' : number || storedNumber}</h2>
      <p>{!storedNumber ? 'ENTER SOME NUMBERS' : `${storedNumber} ${functionType} ${number}`}</p>
    </DisplayStyles>
  );
};

export default Display;
    

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста надССтся, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π» Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ прояснит вопрос ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ…ΡƒΠΊΠΈ React вмСстС с Context API. ИспользованиС встроСнных Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ React Π΄Π°Π΅Ρ‚ ряд прСимущСств:

  • простой для понимания синтаксис ΠΈ отсутствиС бСспорядка Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°Ρ… класса. Π‘ΠΎΠ»ΡŒΡˆΠ΅ Π½ΠΈΠΊΠ°ΠΊΠΈΡ… super ΠΈ constructor – просто чистыС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅;
  • ΠΏΡ€ΠΎΡ‰Π΅ ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ состояниС Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ;
  • Π½Π΅Ρ‚ нСобходимости Π² Redux для Π½Π΅Π±ΠΎΠ»ΡŒΡˆΠΈΡ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ².

React Hooks ΠΈ Context API – ΠΎΡ‚Π»ΠΈΡ‡Π½Ρ‹Π΅ способы ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ прилоТСния React ΠΈ ΠΏΠΈΡΠ°Ρ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ чистый ΠΊΠΎΠ΄. О Π΄Ρ€ΡƒΠ³ΠΈΡ… тСхнологиях React Ρ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ Π² нашСм руководствС для React-Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊΠΈ

ΠŸΠΎΠ΄Π΅Π»ΠΈΡ‚Π΅ΡΡŒ Π² коммСнтариях вашими ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°ΠΌΠΈ Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ дня

Π’ΠΠšΠΠΠ‘Π˜Π˜

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ вакансию
Π Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ C++
Москва, ΠΏΠΎ ΠΈΡ‚ΠΎΠ³Π°ΠΌ собСсСдования

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•