I have created a React App and I am using .Net Core in the backend, the list of data from backend is successfully received, but in react while using Map it only shows one item from the list.I ma using MObX for state management.
My Code is :
import React, { useContext, useEffect } from 'react'
import { RootStoreContext } from '../../app/stores/rootStore';
import { observer } from 'mobx-react-lite';
import { Segment, Item, Icon, Button } from 'semantic-ui-react';
import { format } from 'date-fns';
import { Link } from 'react-router-dom';
const BookList: React.FC = () => {
const rootStore = useContext(RootStoreContext);
const { loadBooks, getAvailableBooks } = rootStore.bookStore;
useEffect(() => {
loadBooks();
}, [loadBooks]);
return (
<div>
{getAvailableBooks.map(books => (
<Segment.Group key={books.bookName}>
<Segment>
<Item.Group>
<Item>
<Item.Image size='tiny' circular src='/assets/user.png' />
<Item.Content>
<Item.Header as='a'>{books.bookName}</Item.Header>
</Item.Content>
</Item>
</Item.Group>
</Segment>
</Segment.Group>
))}
</div>
)
}
export default observer(BookList);
My BookStore is :
import { observable, action, computed, runInAction } from "mobx";
import agent from "../api/agent";
import { RootStore } from "./rootStore";
import { IBooks } from "../models/books";
export default class BookStore {
rootStore: RootStore;
constructor(rootStore: RootStore) {
this.rootStore = rootStore;
}
@observable bookRegistry = new Map();
@observable book: IBooks | null = null;
@observable loadingInitial = false;
@computed get getAvailableBooks() {
return Array.from(this.bookRegistry.values());
}
@action loadBooks = async () => {
this.loadingInitial = true;
try {
const books = await agent.Books.list();
runInAction("loading books", () => {
books.forEach((books) => {
books.issuedOn = new Date(books.issuedOn);
this.bookRegistry.set(books.id, books);
});
this.loadingInitial = false;
});
} catch (error) {
runInAction("load books error", () => {
this.loadingInitial = false;
});
}
};
}
and API is called from agent.ts
import axios, { AxiosResponse } from "axios";
import { history } from "../..";
import { toast } from "react-toastify";
import { IBooks } from "../models/books";
axios.defaults.baseURL = "https://localhost:44396/api";
const requests = {
get: (url: string) => axios.get(url).then(sleep(1000)).then(responseBody),
post: (url: string, body: {}) =>
axios.post(url, body).then(sleep(1000)).then(responseBody),
put: (url: string, body: {}) =>
axios.put(url, body).then(sleep(1000)).then(responseBody),
del: (url: string) => axios.delete(url).then(sleep(1000)).then(responseBody),
};
const Books = {
list: (): Promise<IBooks[]> => requests.get("/Book/GetBookList"),
};
export default {
User
};
export interface IBooks {
id: number;
bookname: string;
issuedOn: Date;
isReturned: boolean;
isRequested: boolean;
isAvailable: boolean;
isTaken: boolean;
name: string;
}
from the screenshot of your API response, it seems that each "book" object does not have an id
property. This might explain why you only see one element rendered, because in your loadBooks
action, each time you try to do this.bookRegistry.set(books.id, books)
, you're using undefined
as the key, and then on the next iteration you overwrite the value stored at that key.