#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