#javascript #reactjs
Вопрос:
Привет, я новичок в Reactjs и практикуюсь в проекте музыкального веб-сайта. Но есть проблема, с которой я застрял. Ну, есть страница с песнями, где я должен показать несколько открыток с песнями.
import React from 'react'
import SongCard from '../components/SongCard';
import { songsList } from '../components/songsList';
//this is first object of the songsList file which i hard coded instead of using api:
export const songsList =[
{
id : 1,
url : './components/Player/Songs/Homayoun Shajarian - Souvashoun.mp3',
image : require('../assets/Souvashoun.jfif').default,
name : 'x',
singer : 'y',
style :'z',
lyrics :'v',
source : './Palyer/Songs/Homayoun Shajarian - Souvashoun.mp3'
}];
export default function Songs() {
return(
<div>
<SongCard className='col-md-6' id={songsList[0].id} image={songsList[0].image} name={songsList[0].name} singer={songsList[0].singer}/><br/>
<SongCard className='col-md-6' id={songsList[1].id} image={songsList[1].image} name={songsList[1].name} singer={songsList[1].singer}/><br/>
<SongCard className='col-md-6' id={songsList[2].id} image={songsList[2].image} name={songsList[2].name} singer={songsList[2].singer}/><br/>
</div>
);
}
а в карточке песни, к которой я прикреплю приведенный ниже код, есть кнопка, предназначенная для перехода на страницу загрузки музыки, чтобы загрузить конкретную песню, на которую была нажата эта кнопка:
import React from 'react'
import {Card, Button} from 'react-bootstrap';
import styled from 'styled-components';
import {BrowserRouter as Router} from 'react-router-dom';
function SongCard(props){
const id = this.props.id;
this.props.history.push({
pathname: '/downloadMusic',
search: '?query=downloadMusic',
state: { data: id }
})
return(
<Styles>
<Router>
<Card style={{ width: '18rem'}} className="cardbg shadow" text="white">
<Card.Img variant="top" src={props.image} className="img-fluid" />
<Card.Body className="text-center">
<Card.Title>آهنگ {props.name}</Card.Title>
<Card.Text>خواننده {props.singer}
</Card.Text>
<Button href="/DownloadMusic/:id" className="btn btn-outline-dark">go to download page</Button>
</Card.Body>
</Card>
</Router>
</Styles>
);
}
export default SongCard;
И, наконец, это последняя страница, которая называется downloadMusic. Здесь также должна быть карточка, содержащая информацию о конкретной песне и кнопку окончательной загрузки.
import React from 'react';
import { songsList } from './songsList';
import DownloadCard from './DownloadCard';
import AudioPlayer from './Player/AudioPlayer';
function DownloadMusic() {
const id = this.props.location.state.data;
const song = songsList.find(item => item.id === id);
return(
<div>
<DownloadCard className='col-md-6' id= {song.id} image={song.image} name={song.name} singer={song.singer}/><br/>
<AudioPlayer/>
</div>
);
}
export default DownloadMusic;
Что я хочу, так это отправить идентификатор и URL-адрес той конкретной песни, которая была нажата на странице песни, на страницу загрузки музыки и показать ее информацию из списка песен в карточке. Я перепробовал так много способов, таких как использование состояния, useParams (), … но ни один из них не сработал для меня. Кроме того, я не хочу отправлять весь реквизит, потому что знаю, что это не лучшая практика. Так что же я делаю не так?
Надеюсь, я поделился достаточной информацией. любая помощь будет признательна.
Ответ №1:
все, что вам нужно сделать, это сопоставить массив песен, как это
import React from 'react'
import React from 'react'
import SongCard from '../components/SongCard';
import { songsList } from '../components/songsList';
//this is first object of the songsList file which i hard coded instead of using api:
const songsList =[
{
id : 1,
url : './components/Player/Songs/Homayoun Shajarian - Souvashoun.mp3',
image : require('../assets/Souvashoun.jfif').default,
name : 'x',
singer : 'y',
style :'z',
lyrics :'v',
source : './Palyer/Songs/Homayoun Shajarian - Souvashoun.mp3'
}];
export default function Songs() {
return(
<div>
{
songsList.map((song, idx) => {
return <SongCard key={idx} className='col-md-6' id={song.id} image={song.image} name={song.name} singer={song.singer}/>
})
}
</div>
);
}
Комментарии:
1. спасибо, что уделили мне время, но это не сработало.
Ответ №2:
Хорошо, я наконец-то нашел способ сделать это, после долгих усилий! Я собираюсь поделиться этим здесь, если кому-то понадобится.
Так что в SongCard.js Я использовал useHistory() и функцию навигации, чтобы сохранить идентификатор и перейти на страницу загрузки музыки, также в атрибуте onClick кнопки используется функция навигации:
import React from 'react'
import {Card, Button} from 'react-bootstrap';
import styled from 'styled-components';
import {BrowserRouter as Router, useHistory} from 'react-router-dom';
function SongCard(props){
//navigating and saving id
const history = useHistory()
const navigate = (id) => {
history.push(`/downloadMusic/${id}`)
}
return(
<Styles>
<Router>
<Card style={{ width: '18rem'}} className="cardbg shadow" text="white">
<Card.Img variant="top" src={props.image} className="img-fluid" />
<Card.Body className="text-center">
<Card.Title>آهنگ {props.name}</Card.Title>
<Card.Text>خواننده {props.singer}
</Card.Text>
//make sure you add onClick attribute!
<Button onClick={() => navigate(props.id)} className="btn btn-outline-dark">download</Button>
</Card.Body>
</Card>
</Router>
</Styles>
);
}
export default SongCard;
Затем в DownloadMusic.js с помощью useRouteMatch() Я получил доступ к параметру id, этот идентификатор был строковым, поэтому на следующем шаге я преобразовал его в номер. В конце с помощью метода .find() я нашел конкретную песню, на которую был нажат!
import React from 'react';
import { songsList } from './songsList';
import DownloadCard from './DownloadCard';
import AudioPlayer from './Player/AudioPlayer';
import { useRouteMatch } from "react-router-dom";
function DownloadMusic() {
//getting id param
const {
params: { id },
} = useRouteMatch('/downloadMusic/:id');
//converting the string id to number:
const num = Number(id);
//finding the song with song.id= num
const song = songsList.find(item => item.id === num);
return(
<div>
<DownloadCard className='col-md-6'
id= {song.id}
url= {song.url}
image={song.image}
name={song.name}
singer={song.singer}
/><br/>
<AudioPlayer id = {song.id}/>
</div>
);
}
export default DownloadMusic;
Просто будьте осторожны с типом идентификатора, это должен быть номер. этот малыш отнял у меня много времени.
🙂 Удачи!
Ответ №3:
Вы можете создать подобную функцию на странице карточки песни
const onSongCardClick = () => {
history.push({
pathname: '/downloadMusic',
state: {id: this.props.id, url: this.props.url}
})
}
...
...
<Button onclick="onSongCardClick()" className="btn btn-outline-dark">go to download page</Button>
И получите эти значения на странице загрузки музыки с помощью
const { id, url } = this.props.location.state
Также передайте URL-адрес в качестве реквизита на карточку песни со страницы песен
Комментарии:
1. Спасибо за ваш ответ. Я сделал то, что вы упомянули, но это снова вызвало ошибку: «Ошибка типа: Не удается прочитать свойство» реквизит «неопределенного», показывая строку, в которой вы инициализировали состояние в onSongCardClick. Я искал решение, но ничего полезного для этого случая не нашел. не могли бы вы помочь с этим, пожалуйста?