Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека совершенным", здесь я хотел бы добавить "Perfect" в начале, тогда цитата будет звучать так: "Совершенная практика делает человека совершенным". Я полный новичок в React js и недавно я сделал приложение для отслеживания бюджета на React.
Будучи полным новичком, я вспомнил цитату, упомянутую ранее, и вместо того, чтобы следовать учебнику YouTube, я связал свою руку, чтобы написать свой первый в жизни проект на React. Несмотря на то, что проект прост и легок в создании, для новичка создать такой проект слишком сложно. Если вы совсем новичок и хотите создать проект, то приложение для отслеживания бюджета - лучший вариант. В этой статье я расскажу вам о своем проекте.
Первым шагом для создания любого проекта react является создание проекта react. Для этого вы можете следовать следующим фрагментам кода. Я назову проект budget_calculator.
Npx create-react-app budget_calculator
Как только вы создали react-приложение, запустите его, чтобы убедиться в его работоспособности.
Npm start
Поскольку наше приложение принимает данные от пользователя и отображает транзакцию, как показано на рисунке. Нам нужно создать папку с двумя компонентами. Я назвал одну из них form для секции ввода, а вторую main для секции отображения или транзакции. Вы можете назвать их по своему усмотрению.
На этом этапе я создал разные компоненты по отдельности, так как мне нравилось четко разделять вещи, чтобы в них было легко ориентироваться и понимать. Давайте подумаем о главном компоненте, в этом компоненте будут отображаться доходы, расходы и остаток. Также в этом разделе будет отображаться транзакция и навигационная ссылка или кнопка для создания формы, верно?
В соответствии с этой концепцией я создал компоненты Budget, Balance, Transaction и Footer. Бюджет является главным компонентом в разделе main, так как он объединяет все компоненты для правильного отображения. Аналогично, компонент Balance будет отображать общие доходы,расходы и общий остаток. Также компонент Transaction будет отображать все транзакции, добавленные пользователем через раздел формы. Наконец, компонент Footer будет использоваться для перехода к следующему разделу формы, чтобы предоставить пользователю раздел ввода.
Далее, для компонента формы компонент AddNew будет выступать в качестве родительского компонента для компонентов Enter и Select. Компонент Select будет содержать элемент выбора, является ли вновь добавленная транзакция доходом или расходом. Кроме того, он будет отображать категорию соответствующего дохода или расхода в соответствии с выбором, сделанным пользователем. Аналогично, компонент Enter будет содержать секцию ввода суммы и описания транзакции. На этом мы закончим эту часть.
Следующая задача - разработать дизайн шаблона или интерфейса. Прежде всего, я разработал его для главного компонента, где отображаются доходы, расходы и транзакции. Вы можете разработать дизайн в соответствии с вашими идеями и творческими способностями. Кроме того, вы можете черпать вдохновение из любого дизайна, доступного в Интернете. Здесь я хотел бы предложить вам сосредоточиться на изучении реакции, а не дизайна.
Я создал и связал отдельные CSS для каждого компонента. Я упомяну конечную структуру файлов и папок моего проекта.
//index.cssbody
{
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', '
Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue '
, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}code
{
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New '
, monospace;
}//App
.css
.App-logo {
height: 40vmin;
pointer-events: none;
}@media
(prefers-reduced-motion: no-preference) {.
App-logo {
animation: App-logo-spin infinite 20s linear;
}}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}}
.App-link {
color: #61dafb;
}@keyframes
App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}}//Balance
.css
.income {
display: inline-block;
margin-right: 50%;
}
.expense {
display: inline-block;
}//Budget
.css
.full {
width: 70%;
height: 80%;
background-color: bisque;
border: 5px solid black;
margin: auto;
}
.hr {
color: black;
}.
App {
text-align: center;
}//Footer
.css
.btn {
background-color: #0c80df;
border: none;
color: white;
padding: 16px 32px;
margin: 2px 0 10px ;
}//Transaction
.css
.in {
color: green;
}
.exp {
color: red;
}
.title, amount {
display: inline-block;
margin: 0;
padding: 1rem;
}.
title {
text-align: left;
}.
amount {
text-align: right;
float: right;
padding-right: 10em;
}//AddNew
.css
.box {
width: 70%;
height: 80%;
background-color: bisque;
border: 5px solid black;
margin: auto;
}
.text {
text-align: center;
}//Enter
.css
.save {
background-color: #0cdf5d;
border: none;
color: white;
padding: 16px 32px;
margin: 10px 10px 10px;
}
.close {
background-color: #6a6e6c;
border: none;
color: white;
padding: 16px 32px;
margin: 10px 10px 10px;
}//Select
.css
.select1 {
display: inline-block;
margin: 5px;
}
.select2 {
display: inline-block;
margin: 5px 0 0 20px;
}
Прежде всего, я устанавливаю react-router-dom для навигации. Затем я импортирую BrowserRouter в компонент index.js. Аналогично, я импортирую Route и Routes в App js для управления маршрутом проекта. Я сделал компонент Budget родительским, а компонент AddNew мог перемещаться по ссылке '/add'.
Npm install react-router-dom
//Index.jsimport
React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
// Если вы хотите начать измерять производительность в своем приложении, передайте функцию//
для логирования результатов (например: reportWebVitals(console.info))
// или отправьте в конечную точку аналитики. Подробнее:
https://bit.ly/CRA-vitalsreportWebVitals();
//App.jsimport
Budget from './components/main/Budget';
import { Route, Routes } from 'react-router';
import AddNew from './components/form/AddNew';
import './App.css';
function App() {
return (
<>
<Routes>
<Route path = '/' element = {<Budget />} />
<Route path = '/add' element = {<AddNew />} />
</Routes>
</>
);
}export
default App;
Компонент AddNew имеет функциональность для выбора и ввода суммы пользовательских транзакций. В этом компоненте я импортировал хук useState и использовал его для создания различных переменных состояния. Состояние option используется для проверки того, является ли транзакция, совершенная пользователем, доходом или расходом. Аналогично, состояния income и expense создаются для хранения типа совершенной транзакции. Аналогично, состояние amount создается для хранения суммы совершенных транзакций. В то время как деталь содержит описание транзакций.
Здесь я импортировал хук useFecth. Это пользовательский хук, и я объясню его позже в статье. Функция handleBudget будет выполняться при отправке формы из компонента enter. Это позволит загрузить и сохранить все введенные пользователем данные.
//AddNew.jsimport
Enter from "./Enter";
import Select from "./Select";
import './AddNew.css';
import { useState, useEffect } from 'react';
import useFetch from ".../.../useFetch";
const AddNew = () => {
const [budget, setBudget] = useFetch('budget', []);
const [option, setOption] = useState('income');
const [income, setIncome] = useState('Зарплата')
const [expense, setExpense] = useState('Образование')
const [amount, setAmount] = useState('')
const [detail, setDetail] = useState('')
const handleBudget = (e) => {
e
.preventDefault();
let budgets = {
option,
amount,
detail,
income: option == 'income' ? income : ''
, expense:option != 'income' ? расход : '
' }
setBudget([...budget, budgets]);
setOption('income ');
setIncome('Salary ');
setExpense('Education ');
setAmount( '')
; setDetail('');
}
// useEffect(() => {
// // dataToNew(budget);
// if (budget?.length){
// localStorage.setItem('budget', JSON.stringify(budget));
// // }
// }, [budget])
return (
<>
<> <div className="text">
<h2>Добавить новый бюджетный список</h2>
<div className="box">
<Select option = {option} setOption = {setOption} income = {income} expense = {expense} setIncome = {setIncome} setExpense = {setExpense} />
<Enter amount = {amount} setAmount = {setAmount} detail = {detail} setDetail = {setDetail} handleBudget = {handleBudget} />
</div>
</div>
</>
)
}export
default AddNew;
//Enter.jsimport
'./Enter.css';
import { NavLink } from 'react-router-dom'
; const Enter = ({ amount, setAmount, detail, setDetail, handleBudget}) => {
return (
<>
<form onSubmit = {handleBudget}}
<h2>Enter Amount</h2>
<input type="number
" placeholder='Enter Amount
' className='amount_field
' onChange = {(e) => setAmount(parseInt(e.target.value))}
value = {amount}
required
/>
<h2>Enter Details</h2>
<input type="text
" placeholder='Enter Details
' className='details_field
' onChange = {(e) => setDetail(e.target.value)}
value = {detail}
required
/>
<br />
<NavLink to = '/'><button className='close'>Cancel</button></NavLink>.
<button type="submit" value="Save" className='save'>Save</button>
</form>
</> </>
)
}export
default Enter;
//Select.jsimport
'./Select.css';
import { useEffect } from 'react';
const Select = ({ option, setOption, income, setIncome, expense, setExpense}) => {
const datas = [
{
id : 1,
income : "Зарплата
", expense : "Образование
" },
{
id : 2,
доход : "Акции
", расход : "Транспорт
" },
{
id : 3,
доход : "ПИФ
", расход : "Мебель
" }
]
useEffect(() => {
setIncome(datas[0]?.income)
setExpense(datas[0]?.expense)
}
, [option])
return (
<div className='data'>
<select className='select1' value= {option} onChange = {(e) => setOption(e.target.value)}>
<option value='income'>Income</option>
<option value='expense'>Expense</option>
</select>
{(option == 'income') ?
<select className='select2' value = {income} key = {datas.id}onChange = {(e) => setIncome(e.target.value)}>
{datas.map((data) => {
return (
<option key = {data.id} value = {data.income} >{data.income}</option>
)
})}
</select>
:
<select className='select2' value = {expense} key = {datas.id} onChange = {(e) => setExpense(e.target.value)}>
{datas.map((data) => {
return (
<option key = {data.id} value = {data.expense}>{data.expense}</option>
)
})}
</select>
}
</div>
)
}export
default Select;
Этот компонент является родительским компонентом главного раздела. Он состоит из тега заголовка для отображения калькулятора бюджета. Кроме того, у него есть дочерние компоненты - Баланс, Транзакция и Нижний колонтитул.
import './Budget.css';
import Balance from './Balance';
import Transaction from './Transaction';
import Footer from './Footer';
const Budget = () => {
return (
<div className="App">
<h2>Калькулятор бюджета</h2>
<div className="full">
<Balance />
<hr className='hr' />
<Transaction />
<Footer />
</div>
</div>
)
} }export
default Budget;
Компонент Balance извлекает данные из useFetch в переменную состояния value. Значение используется для отображения внутри хука useEffect для получения соответствующего ввода пользователя. Такие данные отображаются в разделе доходов или расходов. Сумма будет рассчитана, а остаток будет отображен в разделе Total Balance.
//Balance.jsimport
'./Balance.css';
import useFetch from '.../.../useFetch';
import { useState, useEffect } from 'react';
const Balance = () => {
const [ value ] = useFetch('budget', []);
const [incomeAmount, setIncomeAmount] = useState(0);
const [expenseAmount, setExpenseAmount] = useState(0);
let total_income = 0;
let total_expense = 0;
useEffect(() => {
{value.map((d) => {
if (d.option === 'income' && d.expense === '') {
total_income += d.amount
setIncomeAmount(total_income)
}else{
total_expense += d.amount
setExpenseAmount(total_expense)
}
})}
}, [value])
return (
<div className="top">
<div className="total">
<h3>Общий баланс : Rs {incomeAmount - expenseAmount } </h3>
</div>
<div className="rem">
<div className="income">
<h3>Income</h3>
<p>Rs {incomeAmount} </p>
</div>
<div className="expense">
<h3>Expense</h3>
<p>Rs {expenseAmount}</p>
</div>
</div>
</div>
)
}export
default Balance;
//Transaction.jsimport
'./Transaction.css';
import useFetch from '../../useFetch';
const Transaction = () => {
const [ Value ] = useFetch('budget', []);
return (
<div className="middle">
<h2 style = {{color : 'blue' }}>Transaction</h2>
{Value.map((v) => {
return (
<> {v.option === 'income' ?
<div className="in">
<h3 className='title'>{v.income}</h3>
<p className='amount'>Rs {v.amount}</p>
</div>
:
<div className="exp">
<h3 className='title'>{v.expense}</h3>
<p className='amount'>Rs {v.amount}</p>
</div>
}
</>
)
})}
<hr />
</div>
)
}export
default Transaction;
//Footer.jsimport
'./Footer.css';
import { NavLink } from 'react-router-dom';
const Footer = () => {
return (
<div className="footer">
<NavLink to = '/add'>
<button className='btn'>Add New</button>
</NavLink>
</div>
)
} } export
default Footer;
Этот хук был создан в папке src. Основная цель хука - сохранить ввод пользователя в локальном хранилище и получить каждое значение транзакции для дальнейшего использования. Localstorage.setItem сохраняет вводимые данные в локальном хранилище, а getStorageValue используется для получения данных из локального хранилища.
import { useState, useEffect } from "react";
function getStorageValue(key, []) {
const saved = localStorage.getItem(key);
const initial = JSON.parse(saved);
return initial || [];
}export
const useFetch = (key, []) => {
const [value, setValue] = useState(() => {
return getStorageValue(key, []);
});
useEffect(() => {
// сохранение входного имени
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
};
export default useFetch;
На этом мы подошли к концу руководства по созданию приложения для отслеживания бюджета в React. Мы рассмотрели почти все моменты, необходимые для создания приложения. Надеюсь, вы создали свой бюджетный калькулятор. Если у вас возникли какие-либо проблемы, вы можете посетить мойрепозиторийGitHub или задать свой вопрос прямо в разделе комментариев, я буду рад помочь вам.
20.08.2023 18:21
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".
20.08.2023 17:46
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
19.08.2023 18:39
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.
19.08.2023 17:22
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!
18.08.2023 20:33
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.
14.08.2023 14:49
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.