0
\$\begingroup\$

The react application is showing API fetch result in the page based on query string tag selected.

There are few question in mind to clarify

  1. The way of using map() is correct

  2. There are two functions to call fetch, does ideal ?

Repo: https://github.com/athimannil/news-list/tree/UI

App.js

import React from 'react';
import { BrowserRouter as Router, Route } from "react-router-dom";

import { Newslist } from './newslist/Newslist';

class App extends React.Component {
  render() {
    return (
      <Router>
        <Route sensitive={true} path="/:Tag*" render={(props) => (
            <Newslist {...props} />
          )} />
      </Router>
    );
  }
}

export default App;

Newslist.js

import React from 'react';
import { TagLink } from './../taglink/TagLink';
import { Segment } from '../segment/Segment';

export class Newslist extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      page: 1,
      newsData: [],
      expandedNewsId: null
    }
  }

  componentWillMount() {
    if (Object.keys(this.props.match.params).length == 0) {
    } else {
      this.tag = this.props.match.params.tag;
    }
    this.requestTagNews();
  }

  requestNews () {
    const urlForNews = 'http://localhost:3000/api/';

    let queryString = '?';
    if (this.tag) {
      queryString = `${queryString}tag=${this.tag}&`;
    }
    if (this.page) {
      queryString = `${queryString}page=${this.page}`;
    }

    fetch(`${urlForNews}${queryString}`)
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          newsData: [...this.state.newsData, ...responseJson]
        })
      })
      .catch((error) => {
        console.error(error);
      });
  }
  requestTagNews() {
    this.page = 1;
    const urlForNews = 'http://localhost:3000/api/';
    let queryString ='?';
    if (this.tag) {
      queryString = `${queryString}tag=${this.tag}`;
    }

    fetch(`${urlForNews}${queryString}`)
    .then((response) => response.json())
    .then((responseJson) => {
      this.setState({
        newsData: responseJson
      })
    })
    .catch((error) => {
      console.error(error);
    });
  }

  readMore = (event, newsId) => {
    this.setState({
      expandedNewsId: newsId
    });
  }

  loadMore = (event) => {
    event.preventDefault();
    this.page = this.page + 1;
    this.requestNews();
  }

  filterTag = (tagName) => {
    this.tag = tagName;
    this.requestTagNews();
    this.props.history.push('/'+tagName);
  }

  render () {

    const newsInList = this.state.newsData.map(newsDetails => {
      return (
          <section className="media" key={newsDetails.id}>
            {newsDetails.image && <figure className="media-figure">
               <img src={newsDetails.image} />
            </figure>}
            <div className="media-body">
              <h3 className="media-title">{newsDetails.header}</h3>
              <TagLink links={newsDetails.tags} filterHandler={this.filterTag} />
              {
                newsDetails.content.length > 150 && newsDetails.id != this.state.expandedNewsId
                ? <p>{newsDetails.content.slice(0, 150)}...<a onClick={event => this.readMore(event, newsDetails.id)}>read more</a></p>
                : <p>{newsDetails.content}</p>
              }
            </div>
          </section>
      );
    });
    return (
      <main className="main">
        <Segment filterHandler={this.filterTag} currentTag={this.tag} />
        {
          this.state.newsData.length
          ? <div>
                {newsInList}
                <a className="button load-more" onClick={this.loadMore}>Load more</a>
            </div>
          : <p>Loading...</p>
        }
      </main>
    );
  }
}

TagLink.sj

import React from 'react';

export class TagLink extends React.Component {

  filterTag = (event, link) => {
    this.props.filterHandler(link);
  }

  render () {
    return(
      <ul className="tag-links">
        {
          this.props.links.map((link, i) => {
            return <li key={i} className="tag-links-item"><a onClick={event => this.filterTag(event, link)} name={link}>{link}</a></li>
          })
        }
      </ul>
    );
  }
};

Segment.js

import React from 'react';

export class Segment extends React.Component {

  filterTag = (event) => {
    this.props.filterHandler(event.target.value);
  }

  render() {
    const days = ["Tag 1", "Tag 2", "Tag 3", "Tag 4"];
    const SegmentButton = days.map((day, i) => {
      return (
        <div key={i}>
          <input
            type="radio"
            id={`day-${i + 1}`}
            name="day"
            value={day}
            onChange={this.filterTag}
            checked={ day == this.props.currentTag}
          />
        <label className="segment-button" htmlFor={`day-${i + 1}`}>
            {day}
          </label>
        </div>
      );
    });

    return <div className="segment"> {SegmentButton} </div>;
  }
}
\$\endgroup\$
  • \$\begingroup\$ You should probably include path names. Also, is TagLin.js supposed to be TagLink.js? \$\endgroup\$ – Solomon Ucko Mar 11 '18 at 15:13
  • \$\begingroup\$ @SolomonUcko Sorry I didn't get you \$\endgroup\$ – Muhammed Mar 11 '18 at 15:17
  • \$\begingroup\$ client/components/newslist/Newslist.js instead of Newslist.js, for example. \$\endgroup\$ – Solomon Ucko Mar 11 '18 at 19:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.