Skip to main content

News List

After setting up the project. We can start building our website using ReactSDK features. Let's start with building the home page of Hacker News.

1. Create some news

If you are using ReactSDK Tutorial community, there already exist some news. But if you started with your community, create some posts in the default space of your community (typically named "General").

2. Create NewsList Component

Create a new component named NewsList and route / to it in App.tsx.

App.tsx
import React from 'react';
import {Routes, Route} from "react-router-dom";
import NewsList from "./components/NewsList";

function App() {
return (
<Routes>
<Route path="/" element={<NewsList/>}/>
</Routes>
);
}

export default App;

Now we easily use the useFeed hook to retrieve the data from the community and show it in out website.

components/NewsList.tsx
import React from 'react';
import {simplifyPaginatedResult} from "@tribeplatform/react-sdk/utils";
import {Post} from "@tribeplatform/gql-client/types";
import {useFeed} from "@tribeplatform/react-sdk/hooks";

function NewsList() {
const {data} = useFeed({
fields: {
createdBy: {
member: 'basic'
}
},
variables: {
limit: 10,
}
})
const {nodes: posts} = simplifyPaginatedResult<Post>(data)

return (
<div className="lg:w-3/4 m-auto flex flex-col">
{posts.map((post, i) => (
<div className="flex gap-2 bg-hacker-body p-2" key={post?.id}>
<div className="flex flex-col justify-center">
{i + 1}.
</div>
<div className="flex flex-col flex-grow">
<div>
{post.title}
</div>
<div className="flex gap-2 text-xs text-gray-500">
<div>
By {post.createdBy?.member?.name}
</div>
|
<div>
{post.reactionsCount} upvotes
</div>
|
<div>
{post.repliesCount} comments
</div>
</div>
</div>
</div>
))}
</div>
);
}

export default NewsList;
note

The data retrieved from useFeed is paginated we use simplifyPaginatedResult to flatten them in to an array.

note

The data retrieved from useFeed does not include the post.createdBy by default we have to explicitly specify it in the fields.

Now your website will show the titles of the news.

3. Add infinite scroll

Install react infinite scroller. Unfortunately, the package does not come with typings, so we have to do a little trick to ignore the types. Add typings.d.ts to the src folder.

typings.d.ts
declare module "react-infinite-scroller" {
export default any;
}

Then we can use fetchNextPage and hasNextPage property of useFeed to easily create an infinite scroll.

components/NewsList.tsx
import React from 'react';
import {simplifyPaginatedResult} from "@tribeplatform/react-sdk/utils";
import {Post} from "@tribeplatform/gql-client/types";
import {useFeed} from "@tribeplatform/react-sdk/hooks";
import InfiniteScroll from 'react-infinite-scroller';

function NewsList() {
const {
data,
fetchNextPage,
hasNextPage,
} = useFeed({
fields: {
createdBy: {
member: 'basic'
}
},
variables: {
limit: 10,
}
})
const {nodes: posts} = simplifyPaginatedResult<Post>(data)

return (
<div className="lg:w-3/4 m-auto flex flex-col">
<InfiniteScroll
pageStart={0}
loadMore={fetchNextPage}
hasMore={hasNextPage}
>
{posts.map((post, i) => (
<div className="flex gap-2 bg-hacker-body p-2" key={post?.id}>
<div className="flex flex-col justify-center">
{i + 1}.
</div>
<div className="flex flex-col flex-grow">
<div>
{post.title}
</div>
<div className="flex gap-2 text-xs text-gray-500">
<div>
By {post.createdBy?.member?.name}
</div>
|
<div>
{post.reactionsCount} upvotes
</div>
|
<div>
{post.repliesCount} comments
</div>
</div>
</div>
</div>
))}
</InfiniteScroll>
</div>
);
}

export default NewsList;
note

You can see the final result here.