Реакция If / Else в функции .map

#reactjs

#reactjs

Вопрос:

у меня вопрос. Мне нужно создать приложение, в котором люди могут искать музыку из «LastFM» . Пока все хорошо, я уже кое-что сделал для нормальной работы, но у меня проблема с if / else в функции map, я пытаюсь показать пользователю «результат не найден», если таковые имеются, но безуспешно.Если есть 1 результатов, они будут отображаться на экране, но если есть какие-либо, ничего не произойдет. Вот мой код .

 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=5amp;format=jsonamp;method=artist.searchamp;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   'amp;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) amp;amp; (
                <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;
  

Ответ №1:

У вас там ошибка. Это .map(result: any, index: number, original: []) , значит, вы ссылаетесь на номер индекса с аргументом results :

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

Так что исправьте это, просто не ссылаясь на results в качестве аргумента .map

Ответ №2:

Проблема в том, что вы пытаетесь выполнить if / else в map массива. Но если в массиве нет элементов, то сопоставлять нечего.

Что нужно сделать, так это использовать троичный файл, чтобы проверить, есть ли у массива какие-либо результаты:

 { results amp;amp; 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>
}
  

Здесь мы проверяем, results.length считается ли оно правдивым или нет, если оно равно 1 или выше, то оно отобразит ваш список, в противном случае оно отобразит наше div сообщение пользователю об отсутствии результатов, которые вы можете изменить на любые, которые вы хотите.

Комментарии:

1. да, это сработало, но я хочу отображать «нет результатов» только тогда, когда пользователь нажимает на «поиск»

2. Быстрым и грязным решением этого было бы добавить что-то в state like searched , которое является логическим значением, для которого устанавливается значение true после выполнения пользователем поиска, затем проверьте это в тернарном файле, создав его (results amp;amp; result.length) || !this.state.searched . Однако, вероятно, есть гораздо более приятные способы сделать это.

3. я попробую это . Ty