Целта на този проект е да извлече данни, съхранени във файла db.json в главната директория на нашия проект.
Съдържанието на db.json може да бъде каквото и да е, но в моя случай бях избрал специално кода, използван в fullstack курс uni_of_helsinki. съдържанието на db.json е както по-долу.

{
"anecdotes":[
{
"content": "If it hurts, do it more often",
"id": "47145",
"votes": 0
},
{
"content": "Adding manpower to a late software project makes it later!",
"id": "21149",
"votes": 0
},
{
"content": "The first 90 percent of the code accounts for the first 90 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.",
"id": "69581",
"votes": 0
},
{
"content": "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.",
"id": "36975",
"votes": 0
},
{
"content": "Premature optimization is the root of all evil.",
"id": "25170",
"votes": 0
},
{
"content": "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.",
"id": "98312",
"votes": 0
}
]
}

Пълният код за функционален компонент е както по-долу. Ще се опитам да обясня сравнението на всеки блок от код и какво прави всеки блок от код във функционален и класов компонент.

import React, { useEffect, useState } from 'react'
import axios from 'axios'
const App = () => {
//Here we are using destructuring and setting properties using different hooks
const [anecdotes, setAnecdotes] = useState([])
const [current, setCurrent] = useState(0)
useEffect(() =>{
axios.get('http://localhost:3001/anecdotes').then(response => {
setAnecdotes(response.data)
})
},[])
const handleClick = () => {
setCurrent(Math.round(Math.random() * (anecdotes.length - 1)))
}
if (anecdotes.length === 0) {
return <div>no anecdotes...</div>
}
return (
<div>
<h1>anecdote of the day</h1>
<div>{anecdotes[current].content}</div>
<button onClick={handleClick}>next</button>
</div>
)
}
export default App

Същата операция може да се извърши с помощта на компонент на класа, както е показано по-долу:

import React from 'react'
import axios from 'axios'
class App extends React.Component {
constructor(props) {
super(props)
//Here we are setting state as an object and using its property on later stage to do different operations
this.state = {
anecdotes: [],
current: 0
}
}
componentDidMount = () => {
axios.get('http: //localhost:3001/anecdotes').then(response => {
this.setState({ anecdotes: response.data })
})
}
handleClick = () => {
const current = Math.floor(
Math.random() * this.state.anecdotes.length
)
this.setState({ current })
}
render() {
if(this.state.anecdotes.length === 0) {
return <div>no anecdotes...</div>
}
return (
<div>
<h1>anecdote of the day</h1>
<div>
{this.state.anecdotes[this.state.current].content}
</div>
<button onClick={this.handleClick}>next</button>
</div>
)
}
}
export default App;

След като импортираме библиотеки и в двата случая, ще използваме куки (useEffect, useState).

„useEffect се използва за извличане на данни от файла db.json, записан в корена на проекта. използвайки axios. Докато в компонента на класа същата операция се извършва чрез използване на метода на жизнения цикъл componentDidMount”

операция за извличане на функционален компонент тук

useEffect(() =>{
axios.get(‘http://localhost:3001/anecdotes').then(response => {
setAnecdotes(response.data)
})
},[])

Вътре в useEffect първо извличаме данни, след което записваме данни, използвайки състояние setAnecdote, което се инициализира до празен масив, използвайки кука useState. Има втори аргумент [] след функцията за обратно извикване в куката useEffect. Това се нарича списък със зависимости и както подсказва името, можем да поставим всичко вътре може би id или съобщение. нашият ефект точно useEffect ще зависи от състоянието на елементите в масива със зависимости, имам предвид, че ще стартира ефекта отново за всяка промяна в елемент в списъка със зависимости.

Същата операция се извършва вътре в компонента на класа, като първо се зададе обект с помощта на метода this.stateвътре в конструктора. constructor е метод, който се извиква автоматично за създаване на обект с помощта на клас.

componentDidMount = () => {
axios.get(‘http: //localhost:3001/anecdotes’).then(response => {
this.setState({ anecdotes: response.data })
})
}

Тук трябва да отбележим, че свойството ancdotes е зададено на response.data, което се получава след операция за извличане с помощта на this.setState. ancdotes сега не е празен обект.

Вътре в обекта this.state ще настроим две свойства анекдоти, инициализирани на празен обект, и текущи на 0.
Аналитично, анекдотите във функционалния компонент се задават с помощта на useState кука към празен обект.

Основната разлика между функционалния компонент и компонента на класа е, че във функционално състояние може да се състои от множество различни променливи, като всички те имат своя собствена функция за актуализиране, тук в нашия случай anecodtes действа като променлива и setAnecdotes действа като функция за актуализиране. Докато в клас компонент състояние компонент е единичен обект и се променя чрез метод setState, по-точно this.setState.

Не използвам препратка към документи за всеки термин, дефиниран тук, за да избегна това да стане по-непреодолимо за читателите, въпреки че ще прикача препратка към официалния документ в последния.

След това се дефинира функцията handleClick.

Вътрешен компонент на класа:

handleClick = () => {
const current = Math.floor(
Math.random() * this.state.anecdotes.length
)
this.setState({ current })
}

Първо ще прочетем кода отдясно наляво вътре в обекта this.state, той чете дължина на анекдоти, която е зададена да е празна и след това се умножава с random и след това с Math.floor, за да върне целочислена стойност, която е записан в текущия.
И състоянието му се задава с помощта на this.setState за всяко кликване.

докато във функционалния компонент се извършва същата операция, както по-долу:

const handleClick = () => {
setCurrent(Math.round(Math.random() * (anecdotes.length — 1)))
}

setCurrent се използва за актуализиране на състоянието при всяко щракване.

Следващата стъпка е показване в DOM. Първо ще проверим дали дължината на анекдотите е нула, след което ще покажем „няма анекдоти…“, в противен случай ще покажем съдържанието на анекдотите.

Основната разлика в класа и функционалния компонент тук е, че проверката на дължината се извършва в метода render() и след това се показва в израза за връщане, както е показано по-долу:

render() {
if(this.state.anecdotes.length === 0) {
return <div>no anecdotes…</div>
}
return (
<div>
<h1>anecdote of the day</h1>
<div>
{this.state.anecdotes[this.state.current].content}
</div>
<button onClick={this.handleClick}>next</button>
</div>
)
}

докато, както знаем, няма метод за изобразяване в компонента на класа, така че той се проверява в тялото на приложението на функцията и резултатът се показва в израза за връщане, както е показано по-долу:

if (anecdotes.length === 0) {
return <div>no anecdotes…</div>
}
return (
<div>
<h1>anecdote of the day</h1>
<div>{anecdotes[current].content}</div>
<button onClick={handleClick}>next</button>
</div>
)

Всеки обект може да бъде достъпен от файла db.json, като се използва този ред, както е показано по-долу

` {this.state.anecdotes[this.state.current].content}

докато същата цел във функционалния компонент се постига с помощта на този ред вътре в тага div, както е показано по-долу:

`{анекдоти[current].content}

докато бутонът има манипулатор onClick, който се отнася до дефинираната по-горе функция.

файлът db.json може да бъде извлечен чрез npm i json-сървър

И след това правите, json-сървър — гледайте db.json — порт 3001

екранна снимка за компонента на класа е по-долу:

екранна снимка за функционален компонент е както по-долу:

Това е целият функционален компонент, който е лесен за разбиране и общността се движи към това. Моля, не пропускайте да оставите своя ценен коментар.

изходния код тук:

Разклонете тук: Github repo

Препратки:

„React doc“

JS функция math.floor