0

i have a question . I have to build an app where people can search for music from "lastFm" . So far so good , i already made few things to works normal , but i have a problem with if/else in map function , i've try to show user "no result found" if there are any , but with no luck .If there is 1+ results , will be displayed on the screen , but if there are any , nothing happen . Here is my code .

import React, { Component } from 'react';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';

import {
  TextField,
  Button,
  List,
  ListItem,
  ListItemAvatar,
  ListItemText,
  Avatar,
  Card,
  CardContent
} from '@material-ui/core';
import axios from 'axios';

import './App.css';

const API_URL = 'http://ws.audioscrobbler.com/2.0/?limit=5&format=json&method=artist.search&api_key=' + process.env.REACT_APP_LASTFM_APPKEY;

const isEmpty = (str) => str.length === 0;
class App extends Component {
  state = {
    searchTerm: '',
    savedArtists: []
  }

  componentDidMount() {
    const existing = localStorage.getItem('savedArtists')
    if (existing) {
      this.setState({ savedArtists: JSON.parse(existing) })
    }
  }

  onTextChange = (event) => {
    const value = event.target.value;

    this.setState({ searchTerm: value });
  }

  search = (terms) => {
    const request = API_URL + '&artist=' + terms;

    axios.get(request).then((response) => {
      const results = response.data.results;
      const artists = results.artistmatches.artist.map((artist) => {
        const avatarImage = artist.image.find(image => image.size === 'medium');
        const imageUrl = avatarImage['#text'];
        return { ...artist, avatar: imageUrl }
      });

      this.setState({ artists });
    })
  }

  onSearchClick = () => {
    this.search(this.state.searchTerm);
  }

  clearSearch = () => {
    this.setState({
      searchTerm: '',
      artists: []
    })
  }

  onResultClick = (artist) => {
    this.clearSearch();
    const savedArtists = this.state.savedArtists;
    savedArtists.push(artist)
    this.setState({ savedArtists: savedArtists })
    localStorage.setItem('savedArtists', JSON.stringify(savedArtists));
  }

  render() {
    const results = this.state.artists || [];
    return (
      <div className="App">
        <header className="App-header">
          <AppBar position="static" color="primary">
            <Toolbar className="search-bar">
              <Typography variant="h6" color="inherit">
                Photos
              </Typography>
              <TextField
                placeholder="Search on Last.fm"
                className="search-input"
                onChange={this.onTextChange}
                value={this.state.searchTerm}
              />
              <Button
                onClick={this.onSearchClick}
                variant="contained"
                color="secondary"
                disabled={isEmpty(this.state.searchTerm)}
              >
                Search
              </Button>
              {!isEmpty(this.state.searchTerm) && (
                <Button
                  onClick={this.clearSearch}
                  variant="contained"
                >
                  Clear
                </Button>)
              }
            </Toolbar>
          </AppBar>
        </header>
//****Here is  where i've try to use if/else
        <List className="search-results">
          {
            results.map((artist ,results) => {
              if(results.length === 0)

              return (<ListItem> Not Found</ListItem>

              ); else {
                return (                <ListItem
                  button
                  key={artist.name}
                  className="result"
                  onClick={() => this.onResultClick(artist)}
                >
                  <ListItemAvatar>
                    <Avatar src={artist.avatar} alt={artist.name} />
                  </ListItemAvatar>
                  <ListItemText primary={artist.name} />
                  <Button
                    variant="outlined"
                    color="secondary"
                    size="small"
                    className="add-button"
                  >
                    Add to favorites
                  </Button>
                </ListItem>);
              }


            })

          }
        </List>
        <div className="artist-container">
          {
            this.state.savedArtists.map((artist, i) => {
              return (
                <Card className="artist-card"
                  key={i}
                >
                  <CardContent>
                    {artist.name}
                  </CardContent>
                </Card>
              )
            })
          }
        </div>
      </div>
    );
  }
}

export default App;

2 Answers 2

1

You're having an error there. It's .map(result: any, index: number, original: []), so you're referring to an index number with argument results:

results.map((artist, results) => {
  if(results.length === 0) { ... }
});

So fix it just by not referring to results as a argument of .map

Sign up to request clarification or add additional context in comments.

Comments

0

The problem is that you're trying to do an if/else in the map of the array. But if the array has no items, then there is nothing to map.

What to do is to use a ternary to check if the array has any results:

{ results && result.length ? 
    <List className="search-results">
            {
                results.map((artist) => {
                    return ( 
                    <ListItem button key={artist.name} className="result" onClick={() => this.onResultClick(artist)} >
                        <ListItemAvatar>
                            <Avatar src={artist.avatar} alt={artist.name} />
                        </ListItemAvatar>
                        <ListItemText primary={artist.name} />
                        <Button
                            variant="outlined"
                            color="secondary"
                            size="small"
                            className="add-button"
                        >
                            Add to favorites
                        </Button>
                    </ListItem>
                    );
                })
            }
    </List>
    : <div>No Results</div>
}

Here, we're checking if results.length is considered truthy or not, if it's 1 or higher, then it will render your list, otherwise it will render our div informing the user there is no results, which you can change out to be whatever you want.

3 Comments

yeah , it worked , but i want to display 'no results' only when user click on "search"
A quick and dirty solution to that would be to add something to state like searched which is a boolean that is set to true after the user searches, then check for that in the ternary by making it (results && result.length) || !this.state.searched. There are probably much nicer ways of doing it however.
i'll try this . Ty

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.