ИЗУЧИТЕ КОНТЕКСТ API, СОЗДАВ МИНИ-ПРИЛОЖЕНИЕ ДЛЯ РАБОТЫ С ФИНАНСАМИ

Существуют различные способы управления данными в приложении. Одним из способов управления данными в приложении ReactJs является использование концепции prop drilling. Prop drilling требует, чтобы данные передавались через каждый родительский компонент в дочерний. Этот метод может быть громоздким и не совсем масштабируемым.

В этой статье мы рассмотрим концепцию Context API, которая упрощает управление состоянием приложения. Сначала нам нужно понять, что такое контекст, как он может быть реализован в приложении React, а затем мы создадим прототип банковского приложения для правильного понимания. Для правильного понимания этой статьи потребуются некоторые знания React и JavaScript. Давайте сначала дадим определение контекста. Прежде чем приступить к этому, вы должны иметь базовые знания о ReactJs.

Контекст

Context предоставляет возможность передавать данные по дереву компонентов без необходимости передавать реквизиты на каждом уровне вниз. Это означает, что управление данными осуществляется глобально. С помощью Context данные могут быть установлены глобально; при этом они доступны непосредственно любому из дочерних компонентов без необходимости передавать их через каждый родительский элемент. Проще говоря, Context помогает нам избежать вложенности на уровне различных компонентов для доступа к данным.
У Context есть несколько API, а именно: React.createContext, Context.Cosumer, Context.Provider и т.д. В этой статье мы сосредоточимся на React.createContext и Context.Provider.

Давайте создадим наше приложение в следующих шагах. Создадим react-приложение с помощью create-react-app.

Мы будем использовать компонент Material UI для стилизации различных интерфейсов.
Наше приложение должно показать, как управляется состояние на экранах депозита, баланса и снятия средств в нашем финансовом приложении.
После создания приложения fakebank с помощью create-react-app, в папке src мы создадим папку components, в которой будут храниться все наши папки, включая компонент context. В папке компонента создадим файл context.js. Папка context — это место, где происходит управление всем состоянием приложения.

В компонент контекста будут импортированы некоторые компоненты из react, а именно useState и useContext.

import React from {useState, useContext}
Вход в полноэкранный режим Выйти из полноэкранного режима

Далее мы вызываем метод createContext, который обеспечивает передачу данных по дереву компонентов без необходимости вручную передавать реквизиты на каждом уровне.

import React from {useState, useContext}
import React, { useState, useContext } from "react";

const AppContext = React.createContext();
Вход в полноэкранный режим Выход из полноэкранного режима

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

import React, { useState, useContext } from "react";

const AppContext = React.createContext();

const AppProvider = ({ children }) => {
  const initialValues = { balance: 0, deposit: 0, withdrawal: 0 };
  const [inputValue, setInputValue] = useState(initialValues);

  let walletBalance = inputValue.balance;
  let amountDeposit = inputValue.deposit;
  let amountWithdrawn = inputValue.withdrawal;
Вход в полноэкранный режим Выйти из полноэкранного режима

Функция выше будет возвращать дочерние реквизиты, обернутые AppContext.Provider. Провайдер позволяет потребляющим компонентам подписываться на изменения в контексте. Далее мы экспортируем наши компоненты AppContext и AppProvider. Но сначала мы настроим пользовательский хук, чтобы сделать наш код чище. (ПРИМЕЧАНИЕ: Вы можете не использовать пользовательский хук)

import React, { useState, useContext } from "react";

const AppContext = React.createContext();

const AppProvider = ({ children }) => {
  const initialValues = { balance: 0, deposit: 0, withdrawal: 0 };
  const [inputValue, setInputValue] = useState(initialValues);

  let walletBalance = inputValue.balance;
  let amountDeposit = inputValue.deposit;
  let amountWithdrawn = inputValue.withdrawal;


 return (
    <AppContext.Provider>
      {children}
    </AppContext.Provider>
  );

}

//custom hook

const useGlobalContext = () => {
  return useContext(AppContext);
};

export { useGlobalContext, AppProvider };
Вход в полноэкранный режим Выход из полноэкранного режима

Мы обернем компонент App в файле index.js экспортированным AppProvider.

<React.StrictMode>
    <AppProvider>
      <App />
    </AppProvider>
  </React.StrictMode>
Вход в полноэкранный режим Выйти из полноэкранного режима

Далее передадим значения начального состояния нашего приложения компоненту AppProvider.

import React, { useState, useContext } from "react";

const AppContext = React.createContext();

const AppProvider = ({ children }) => {
  const initialValues = { balance: 0, deposit: 0, withdrawal: 0 };
  const [inputValue, setInputValue] = useState(initialValues);

  let walletBalance = inputValue.balance;
  let amountDeposit = inputValue.deposit;
  let amountWithdrawn = inputValue.withdrawal;


 return (
    <AppContext.Provider value={{
        walletBalance,
        amountDeposit,
        amountWithdrawn,
      }}>
      {children}
    </AppContext.Provider>
  );

}

//custom hook

const useGlobalContext = () => {
  return useContext(AppContext);
};

export { useGlobalContext, AppProvider };
Войти в полноэкранный режим Выход из полноэкранного режима

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

import React from "react";
import {
  Box,
  Card,
  CardContent,
  Typography,
  CardActions,
  Button,
  Divider,
} from "@mui/material";


const Deposit = () => {
  return (
    <Box
      sx={{
        marginTop: "10rem",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Card sx={{ minWidth: 700, background: "#A52A2A", color: "white" }}>
        <CardContent>
          <Typography
            sx={{ fontSize: 20, textAlign: "center", fontWeight: "bold" }}
            gutterBottom
          >
            Deposit
          </Typography>
          <Divider color="white" />

          <Box
            sx={{ display: "flex", justifyContent: "space-around", mt: "1rem" }}
          >
            <Typography sx={{ mb: 1.5, color: "white" }} color="text.secondary">
              Balance
            </Typography>
            <Typography sx={{ mb: 1.5, color: "white" }} color="text.secondary">
              $100
            </Typography>
          </Box>

          <Typography sx={{ fontWeight: "bold" }}>Deposit Amount</Typography>
          <form>
            <input
              type="text"
              id="deposit"
              name="deposit"
              value="deposit"
            />
          </form>
        </CardContent>
        <CardActions>
          <Button
            variant="contained"
            sx={{ background: "white", color: "black" }}

          >
            Deposit
          </Button>
        </CardActions>
      </Card>
    </Box>
  );
};

export default Deposit;

Вход в полноэкранный режим Выход из полноэкранного режима

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

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

import React, { useState, useContext } from "react";

const AppContext = React.createContext();

const AppProvider = ({ children }) => {
  const initialValues = { balance: 0, deposit: 0, withdrawal: 0 };
  const [inputValue, setInputValue] = useState(initialValues);

  let walletBalance = inputValue.balance;
  let amountDeposit = inputValue.deposit;
  let amountWithdrawn = inputValue.withdrawal;


  //handle input change
  const handleChange = (e) => {
    const { name, value } = e.target;
    setInputValue({ ...inputValue, [name]: value });
  };

  return (
    <AppContext.Provider
      value={{
        walletBalance,
        amountDeposit,
        amountWithdrawn,
        handleChange, 
      }}
    >
      {children}
    </AppContext.Provider>
  );
};

//custom hook

const useGlobalContext = () => {
  return useContext(AppContext);
};

export { useGlobalContext, AppProvider };

Вход в полноэкранный режим Выход из полноэкранного режима

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

const { walletBalance, amountDeposit, handleChange } =
    useGlobalContext();
Вход в полноэкранный режим Выход из полноэкранного режима

Ниже показаны значения, передаваемые в компонент deposit.

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

import React from "react";
import {
  Box,
  Card,
  CardContent,
  Typography,
  CardActions,
  Button,
  Divider,
} from "@mui/material";
import { useGlobalContext } from "./context";

const Deposit = () => {
  const { walletBalance, amountDeposit, handleChange } =
    useGlobalContext();
  return (
    <Box
      sx={{
        marginTop: "10rem",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Card sx={{ minWidth: 700, background: "#A52A2A", color: "white" }}>
        <CardContent>
          <Typography
            sx={{ fontSize: 20, textAlign: "center", fontWeight: "bold" }}
            gutterBottom
          >
            Deposit
          </Typography>
          <Divider color="white" />

          <Box
            sx={{ display: "flex", justifyContent: "space-around", mt: "1rem" }}
          >
            <Typography sx={{ mb: 1.5, color: "white" }} color="text.secondary">
              Balance
            </Typography>
            <Typography sx={{ mb: 1.5, color: "white" }} color="text.secondary">
              {walletBalance}
            </Typography>
          </Box>

          <Typography sx={{ fontWeight: "bold" }}>Deposit Amount</Typography>
          <form>
            <input
              type="text"
              id="deposit"
              name="deposit"
              value={amountDeposit}
              onChange={handleChange}
            />
          </form>
        </CardContent>
        <CardActions>
          <Button
            variant="contained"
            sx={{ background: "white", color: "black" }}
          >
            Deposit
          </Button>
        </CardActions>
      </Card>
    </Box>
  );
};

export default Deposit;

Вход в полноэкранный режим Выход из полноэкранного режима

Это будет повторено на двух других экранах, а именно: вывод средств и баланс.

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

 //handle incrementing the deposit made to update balance
  const handleAmount = (e) => {
    e.preventDefault();

    if (regex.test(amountDeposit)) {
      walletBalance += parseInt(amountDeposit);
      inputValue.balance = walletBalance;
      setInputValue({ ...inputValue, walletBalance });
      amountDeposit = "";
      inputValue.deposit = amountDeposit;
      setInputValue({ ...inputValue, amountDeposit });
    } else {
      alert("You have entered an invalid character!!!");
    }
  };
Вход в полноэкранный режим Выход из полноэкранного режима

Функции обновляют баланс после внесения депозита.

 //handle withdrawals
  const withdrawalHandler = (e) => {
    e.preventDefault();
    if (regex.test(amountWithdrawn)) {
      walletBalance -= parseInt(amountWithdrawn);
      inputValue.balance = walletBalance;
      setInputValue({ ...inputValue, walletBalance });
      amountWithdrawn = "";
      inputValue.withdrawal = amountWithdrawn;
      setInputValue({ ...inputValue, amountWithdrawn });
    } else {
      alert("You have entered an invalid character!!!");
    }
  };
Вход в полноэкранный режим Выход из полноэкранного режима

Передайте сумму handleAmount и сумму withdrawalHandler в провайдер и получите ее деструктуризацию в соответствующих компонентах.

<AppContext.Provider
      value={{
        walletBalance,
        amountDeposit,
        amountWithdrawn,
        handleChange,
        handleAmount,
        withdrawalHandler,
      }}
    >
      {children}
    </AppContext.Provider>
Вход в полноэкранный режим Выход из полноэкранного режима

UseGlobalContext для вывода и ввода средств должен выглядеть следующим образом:

const { walletBalance, amountDeposit, handleChange, handleAmount } =
    useGlobalContext();
Вход в полноэкранный режим Выход из полноэкранного режима

и

const { walletBalance, amountWithdrawn, handleChange, withdrawalHandler } =
    useGlobalContext();
Войти в полноэкранный режим Выйти из полноэкранного режима

Таким образом, компоненты баланса:

import React from "react";
import {
  Box,
  Card,
  CardContent,
  Typography,
  Divider,
} from "@mui/material";
import { useGlobalContext } from "./context";

const Balance = () => {
  const { walletBalance } = useGlobalContext();
  return (
    <Box
      sx={{
        marginTop: "10rem",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      <Card sx={{ minWidth: 700, background: "#A52A2A", color: "white" }}>
        <CardContent>
          <Typography
            sx={{ fontSize: 20, textAlign: "center", fontWeight: "bold" }}
            gutterBottom
          >
            Balance
          </Typography>
          <Divider color="white" />

          <Box
            sx={{ display: "flex", justifyContent: "space-around", mt: "1rem" }}
          >
            <Typography sx={{ mb: 1.5, color: "white" }} color="text.secondary">
              Balance
            </Typography>
            <Typography sx={{ mb: 1.5, color: "white" }} color="text.secondary">
              {walletBalance}
            </Typography>
          </Box>
        </CardContent>
      </Card>
    </Box>
  );
};

export default Balance;

Вход в полноэкранный режим Выход из полноэкранного режима

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

Оцените статью
devanswers.ru
Добавить комментарий