0

I'm using ReactJS to run my Front and ExpressJS to run my API. So at my ReactJS App, I want to show only array id: 8 to id: 12 for example, because this way I have the code it prints all the arrays.

import React, {Component} from 'react';
import AppHeader from './AppHeader.js';
import './AppHomepage.css';
import {Link} from 'react-router-dom';

class AppHomepage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            Book: []
        }
    }
    componentDidMount() {
        this.getList();
    }
    getList = () => {
        fetch('/api')
            .then(res => res.json())
            .then(Book => this.setState({Book}))
    }
    render() {
        return (
            <div>
                <AppHeader />
                <div className="hpcontainer">
                    <div className="hpholder">
                        <h1 className="hptitle">Kuran Shqip</h1>
                        <p className="hptxt">Një projekt sadaka kushtuar lexuesve të Kuranit famëlartë.</p>
                        <div className="hpsurahlist">
                            {this.state.Book.map(Book =>
                                <Link to={Book.path} className="hpsurah">
                                    <p className="hpid">{Book.id}</p>
                                    <div>
                                        <h2 className="hpsurahsq">{Book.surah}</h2>
                                        <h1 className="hpsurahen">{Book.surahsq}</h1>
                                        <h3 className="hpnumber">{Book.verses}</h3>
                                    </div>
                                </Link>)}
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

export default AppHomepage;

I tried this from someone In the comments but didn't work

{this.state.Book.filter(Book => Book.id >= 8 && Book.id <= 12).map(Book =>
                                <Link to={Book.path} className="hpsurah">
                                    <p className="hpid">{Book.id}</p>
                                    <div>
                                        <h2 className="hpsurahsq">{Book.surah}</h2>
                                        <h1 className="hpsurahen">{Book.surahsq}</h1>
                                        <h3 className="hpnumber">{Book.verses}</h3>
                                    </div>
                                </Link>)}
grudinsky
  • 108
  • 6
  • If you don't want to store the filtered array in state, you can chain array methods by performing the below in your div: `this.state.Book.filter(item=>item.id >=8 && item.id<=12).map(item=>...` – grudinsky Feb 09 '21 at 20:05
  • Alternatively you can perform the same filtering in your `setState` on fetch if you are only planning to only work with that data. – grudinsky Feb 09 '21 at 20:13
  • Thank you for the reply, so I want to use again that data below the div, for example, I will report that for each row. –  Feb 09 '21 at 20:17
  • @grudinsky I added this {this.state.book.filter(book=> book.id >= 8 && book.id <= 12).map(quran => and is not working, for example –  Feb 09 '21 at 20:27
  • Not sure if I understand your above comment correctly, but in order to avoid duplicated filtering with the same conditions you can do this in your last .then block of your fetch function and then map filteredBooks as you had it in your code: `.then(Book => this.setState({filteredBooks: Book.filter(item=> item.id >=8 && item.id <=12)}) ` – grudinsky Feb 09 '21 at 20:27
  • @grudinsky {this.state.Book.filter(Book => Book.id >= 8 && Book.id <= 12).map(Book =>

    {Book.id}

    {Book.surah}

    {Book.surahsq}

    {Book.verses}

    )}
    –  Feb 09 '21 at 20:30
  • @grudinsky Didn't work that way –  Feb 09 '21 at 20:30
  • What errors are you getting? Also I'd suggest changing your naming conventions and not use the same upper scope names inside the array methods as I assume one of the errors you are getting that Book has already been declared in the upper scope in map and filter. – grudinsky Feb 09 '21 at 20:39
  • @grudinsky I'm not getting any error, but with your method, I can't seem to get it to work, the data doesn't load. Can you take that code I shared and edit and add what I need to add so I can just copy and paste it. –  Feb 09 '21 at 20:47

2 Answers2

0

This has nothing to do with React, per se. You're mapping the entire array in to links, so you get all of them. If you want a subset, you can use Array#slice.

const arr = [1, 2, 3, 4, 5, 6, 7, 8]
const subset = arr.slice(2, 5) // <-- [ 3, 4, 5 ]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

Eric Haynes
  • 5,126
  • 2
  • 29
  • 36
  • So I should use this js on this file I shared or at the API express? –  Feb 09 '21 at 20:18
  • Without knowing anything about your server, it's _usually_ better to paginate on the backend. There could be millions of `Book`s one day. But that would be limited by your lookup e.g. in the database, which would then only have the subset passed to the React app. – Eric Haynes Feb 09 '21 at 20:57
0

As requested in the comments, if you really have numeric id's that also include 8, 12 and numbers in between, the below snippet should work:

{this.state.Book.filter(item =>
     Number(item.id) >= 8 && Number(item.id) <= 12).map(item =>
            <Link to={item.path} className="hpsurah">
                 <p className="hpid">{item.id}</p>
                 <div>
                     <h2 className="hpsurahsq">{item.surah}</h2>
                     <h1 className="hpsurahen">{item.surahsq}</h1>
                     <h3 className="hpnumber">{item.verses}</h3>
                 </div>
            </Link>
)}
grudinsky
  • 108
  • 6
  • Converts your string type to number type for number comparison but in theory it should also work without this given that your id's are really "8",..."12". [more about Number() and parseInt()](https://stackoverflow.com/questions/4090518/what-is-the-difference-between-parseint-and-number) – grudinsky Feb 09 '21 at 21:11