Търсите да подобрите уменията си за развитие на React? Създайте своя собствена версия на Hacker News с помощта на това ръководство.

Hacker News е популярен уебсайт сред предприемачи и разработчици. Включва съдържание, фокусирано върху компютърните науки и предприемачеството.

Опростеното оформление на Hacker News може да подхожда на определени хора. Въпреки това, ако желаете по-привлекателна и персонализирана версия, можете да използвате полезни API, за да създадете свое собствено персонализирано изживяване с Hacker News. Освен това изграждането на клонинга на Hacker News може да ви помогне да затвърдите уменията си за React.

Настройка на проекта и сървъра за разработка

Кодът, използван в този проект, е наличен в a GitHub хранилище и е безплатен за използване под лиценза на MIT.

За стилизиране копирайте съдържанието на index.css файл от хранилището и ги поставете във вашия собствен index.css файл. Ако искате да разгледате версия на живо на този проект, можете да проверите това демонстрация.

instagram viewer

Пакетите, необходими за този проект, включват:

  • React Router за обработка на маршрутизирането в Едностранично приложение (SPA).
  • HTMLReactParser за анализиране на HTML, върнат от Интерфейс за програмиране на приложения (API).
  • MomentJS за обработка на датите, върнати от API.

Отворете терминала и стартирайте:

прежда създават vite

Можете също да използвате Мениджър на пакети на възли (NPM) ако го предпочитате пред прежда. Командата по-горе трябва да използва инструмента за изграждане на Vite за скеле на основен проект. Наименувайте проекта си и когато бъдете подканени за рамката, изберете Реагирайте и задайте варианта на JavaScript.

Сега cd в папката на проекта и инсталирайте споменатите по-рано пакети, като изпълните следните команди в терминала:

yarn добави html-react-parser
прежда добавете реакция-рутер-дом
момент добавяне на прежда
разработка на прежда

След като инсталирате всички пакети и стартирате сървъра за разработка, отворете проекта във всеки редактор на код и създайте три папки в src папка а именно: компоненти, кукички, и страници.

В компоненти папка, добавете два файла Comments.jsx и Navbar.jsx. В кукички папка, добавете един файл useFetch.jsx. Тогава в страници папка, добавете два файла ListPage.jsx и PostPage.jsx.

Изтрийте App.css файл и заменете съдържанието на main.jsx файл със следното:

импортиране Реагирайте от"реагира"
импортиране {BrowserRouter} от'react-router-dom'
импортиране ReactDOM от'react-dom/клиент'
импортиране Приложение от'./App.jsx'
импортиране'./index.css'

ReactDOM.createRoot(документ.getElementById("корен")).render(



</BrowserRouter>
</React.StrictMode>,
)

В App.jsx файл, премахнете целия шаблонен код и модифицирайте файла така, че да ви остане само функционалният компонент:

функцияПриложение() {
връщане (
<>
</>
)
}

износпо подразбиране Приложение

Импортирайте необходимите модули:

импортиране { Маршрути, Маршрут } от'react-router-dom'
импортиране ListPage от'./pages/ListPage'
импортиране Навигационна лента от'./components/Navbar'
импортиране PostPage от'./pages/PostPage'

Във фрагмента на React добавете Маршрути компоненти с три Маршрут дъщерни компоненти с пътища: /, /:type, и /item/:id съответно.


'/'
елемент={<> <Навигационна лента /><ListPage /></>}>
</Route>
'/:Тип'
елемент={<> <Навигационна лента /><ListPage /></>}>
</Route>
'/item/:id'
елемент={}>
</Route>
</Routes>

Създаване на потребителската кука useFetch

Този проект използва два API. Първият API отговаря за извличането на списъка с публикации в дадена категория (тип), докато вторият API е API на Algolia, който отговаря за извличането на определена публикация и нейните коментари.

Отвори useFetch.jsx файл, дефинирайте куката като експорт по подразбиране и импортирайте useState и useEffect кукички.

импортиране {useState, useEffect} от"реагира";
износпо подразбиранефункцияuseFetch(тип, id) {

}

Дефинирайте три променливи на състоянието, а именно: данни, грешка, и Зареждане, със съответните им функции за настройка.

конст [данни, setData] = useState();
конст [грешка, setError] = useState(невярно);
конст [зареждане, setLoading] = useState(вярно);

След това добавете a useEffect кука със зависимостите: документ за самоличност и Тип.

useEffect(() => {
}, [id, тип])

След това във функцията за обратно извикване добавете функцията fetchData() за извличане на данните от подходящите API. Ако предаденият параметър е Тип, използвайте първия API. В противен случай използвайте втория API.

асинхроненфункцияfetchData() {
позволявам отговор, url, параметър;
ако (Тип) {
url = " https://node-hnapi.herokuapp.com/";
параметър = type.toLowerCase();
}
другоако (документ за самоличност) {
url = " https://hn.algolia.com/api/v1/items/";
параметър = id.toLowerCase();
}
опитвам {
отговор = изчакайте извличане (`${url}${параметър}`);
} улов (грешка) {
setError(вярно);
}

ако (отговор) ако (отговор.състояние !== 200) {
setError(вярно);
} друго {
позволявам данни = изчакайте response.json();
setLoading(невярно);
setData (данни);
}
}
fetchData();

Накрая върнете Зареждане, грешка, и данни променливите на състоянието като обект.

връщане { зареждане, грешка, данни };

Изобразяване на списък с публикации в зависимост от заявената категория

Всеки път, когато потребителят навигира до / или /:type, React трябва да изобрази ListPage компонент. За да приложите тази функционалност, първо импортирайте необходимите модули:

импортиране {useNavigate, useParams} от"react-router-dom";
импортиране useFetch от"../hooks/useFetch";

След това дефинирайте функционалния компонент и след това задайте динамичния параметър, Тип към Тип променлива. Ако динамичният параметър не е наличен, задайте Тип променлива към Новини. След това се обадете на useFetch кука.

износпо подразбиранефункцияListPage() {
позволявам {тип} = useParams();
конст навигация = useNavigate();
ако (!тип) тип = "Новини";
конст { зареждане, грешка, данни } = useFetch (тип, нула);
}

След това върнете подходящия JSX код в зависимост от това кой от Зареждане, грешка, или данни променливи е вярно.

ако (грешка) {
връщане<див>Нещо се обърка!див>
}

ако (Зареждане) {
връщане<див>Зарежданедив>
}

ако (данни) {
документ.title = type.toUpperCase();
връщане<див>

'тип списък'>{type}</div>
{data.map(вещ =>
"вещ">
"артикул-заглавие"
onClick={() => навигация(`/елемент/${item.id}`)}>
{item.title}
</div>
{item.domain &&
"артикул-връзка"
onClick={() => отворен(`${item.url}`)}>
({item.domain})</span>}
</div>)}
</div>
</div>
}

Създаване на компонент PostPage

Първо импортирайте подходящите модули и компоненти, след това дефинирайте функционалния компонент по подразбиране, задайте документ за самоличност динамичен параметър към документ за самоличност променлива и извикайте useFetch кука. Уверете се, че деструктурирате отговора.

импортиране { Връзка, useParams } от"react-router-dom";
импортиране анализирам от'html-react-parser';
импортиране момент от"момент";
импортиране Коментари от"../components/Comments";
импортиране useFetch от"../hooks/useFetch";

износпо подразбиранефункцияPostPage() {
конст { id } = useParams();
конст { зареждане, грешка, данни } = useFetch(нула, документ за самоличност);
}

И точно както при ListPage компонент, визуализира подходящия JSX въз основа на състоянието на следните променливи: Зареждане, грешка, и данни.

ако (грешка) {
връщане<див>Нещо се обърка!див>
}

ако (Зареждане) {
връщане<див>Зарежданедив>
}

ако (данни) {
документ.title=data.title;
връщане<див>

"след заглавие">{данни.заглавие}</div>
"пост-метаданни">
{data.url &&
className="пост-линк">Посетете уебсайта</Link>}
"пост-автор">{data.author}</span>
"след време">
{moment (data.created_at).fromNow()}
</span>
</div>
{data.text &&
"след текст">
{parse (data.text)}</div>}
"след коментари">
"коментари-етикет">Коментари</div>

</div>
</div>
}

Импортирайте анализирам модул и момент модул. Дефинирайте функционалния компонент по подразбиране Коментари който приема в commentsData масив като опора, преминава през масивите и изобразява a Възел компонент за всеки елемент.

импортиране анализирам от'html-react-parser';
импортиране момент от"момент";

износпо подразбиранефункцияКоментари({ commentsData }) {
връщане<>
{commentsData.map(commentData =><ВъзелcommentData={commentData}ключ={commentData.id}
/>)}
</>
}

След това дефинирайте Възел функционален компонент точно под Коментари компонент. The Възел компонент изобразява коментара, метаданните и отговаря на всеки коментар (ако има такъв) чрез рекурсивно изобразяване на себе си.

функцияВъзел({ commentData }) {
връщане<дивclassName="коментар">
{
commentData.text &&
<>
'коментар-метаданни'>
{commentData.author}</span>

{moment (commentData.created_at).fromNow()}
</span>
</div>
'коментар-текст'
>
{parse (commentData.text)}</div>
</>
}
'коментар-отговори'
>
{(commentData.children) &&
commentData.children.map(дете =>
)}
</div>
</div>
}

В кодовия блок по-горе, анализирам е отговорен за анализирането на HTML, съхраняван в commentData.text, докато момент отговаря за анализирането на времето на коментара и връщането на относителното време с помощта на от сега() метод.

Създаване на компонента Navbar

Отвори Navbar.jsx файл и импортирайте NavLink модул от реагират-рутер-дом модул. Накрая дефинирайте функционалния компонент и върнете родител нав елемент с пет NavLink елементи, сочещи към съответните категории (или типове).

импортиране { NavLink } от"react-router-dom"

износпо подразбиранефункцияНавигационна лента() {
връщане<нав>
"/Новини">Начало</NavLink>
"/най-добър">Най-добър</NavLink>
"/покажи">Покажи</NavLink>
"/питам">Попитайте</NavLink>
"/работни места">Работа</NavLink>
</nav>
}

Поздравления! Току-що създадохте свой собствен клиент за Hacker News.

Затвърдете вашите React умения чрез изграждане на приложение за клониране

Изграждането на клонинг на Hacker News с React може да ви помогне да затвърдите уменията си за React и да осигурите практично приложение за една страница, върху което да работите. Има много начини, по които можете да продължите нещата. Например, можете да добавите възможност за търсене на публикации и потребители към приложението.

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