Я создаю приложение Spotify с его API. Я хочу 4 просмотра (например, '/', 'nowPlaying', 'favouriteArtists', 'favouriteSongs').
Мне нужен setAccessToken для использования таких функций, как getMyCurrentPlaybackState(), на каждой новой странице, верно? Idk, если мне нужно if (params.access_token){spotifyWebApi.setAccessToken(params.access_token)} в каждом контейнере, который будет использовать такие функции, как getMyCurrentPlaybackState(). Я думал о создании контейнера Spotify.jsx, который обрабатывает хранилище объекта Spotify (который используется в токене и в каждом контейнере, использующем функции spotify). Но с этим Spotify.jsx я не знаю, является ли это хорошим подходом, и как connect использовать его необходимую константу spotifyWebApi для каждого файла контейнера и файла токена.
Для лучшего понимания моей идеи: я бы создал Token.jsx с getHashParams() и Playing.jsx с getNowPlaying(). Каждому нужен spotifyWebApi const.
import React, { Component } from 'react';
import Spotify from 'spotify-web-api-js';
const spotifyWebApi = new Spotify();
class App extends Component {
constructor(){
super();
const params = this.getHashParams();
this.state = {
loggedIn: params.access_token ? true : false,
nowPlaying: {
name: 'Not Checked',
image: ''
}
}
if (params.access_token){
spotifyWebApi.setAccessToken(params.access_token)
}
}
getHashParams() {
var hashParams = {};
var e, r = /([^&;=]+)=?([^&;]*)/g,
q = window.location.hash.substring(1);
while ( e = r.exec(q)) {
hashParams[e[1]] = decodeURIComponent(e[2]);
}
return hashParams;
}
getNowPlaying(){
spotifyWebApi.getMyCurrentPlaybackState()
.then((response) => {
this.setState({
nowPlaying: {
name: response.item.name,
image: response.item.album.images[0].url
}
})
})
}
}






Вместо того, чтобы передавать эту константу другим компонентам, я бы создал SpotifyUtils.jsx и внутри него объявил бы константу. И в этом вспомогательном файле я бы экспортировал функции, чтобы другие компоненты могли их использовать.
Например:
import Spotify from 'spotify-web-api-js';
const spotifyWebApi = new Spotify();
let token = null
export function isLoggedIn() {
return !!token
}
export function setAccessToke(_token) {
token = _token;
spotifyWebApi.setAccessToken(_token);
}
export function getNowPlaying(){
return spotifyWebApi.getMyCurrentPlaybackState()
.then((response) => {
return {
name: response.item.name,
image: response.item.album.images[0].url
}
})
}
Чтобы в компонентах можно было использовать их так:
import React, { Component } from 'react';
import {
isLoggedIn,
setAccessToken,
getNowPlaying,
} from 'helpers/SpotifyUtils'
class App extends Component {
constructor(){
super();
this.state = {
loggedIn: isLoggedIn(),
nowPlaying: {
name: 'Not Checked',
image: ''
}
}
getHashParams() {
var hashParams = {};
var e, r = /([^&;=]+)=?([^&;]*)/g,
q = window.location.hash.substring(1);
while ( e = r.exec(q)) {
hashParams[e[1]] = decodeURIComponent(e[2]);
}
return hashParams;
}
componentDidMount() {
if (!this.state.loggedIn) {
const params = this.getHashParams();
if (params.access_token) {
setAccessToken(params.access_token)
getNowPlaying()
.then(nowPlaying => this.setState({ nowPlaying }))
}
}
}
}
Это позволит повторно использовать вашу константу spotifyWebApi в любом компоненте, который вы импортируете вспомогательные функции. Мне особенно нравится этот шаблон, когда я создаю utils или helpers обычным образом, чтобы вы могли легко повторно использовать код. Кроме того, если Spotify Web Api выпустит критическое изменение, ваш рефакторинг будет проще, потому что вам нужно будет реорганизовать только файл SpotifyUtils.jsx, поскольку он будет единственным файлом, использующим import Spotify from 'spotify-web-api-js'.
Предполагалось, что это будет params.access_token, который был в вашем примере
В вашем заголовке упоминается Redux, но я не вижу, чтобы ваш код его использовал. С Redux вы можете получить access_token, а затем сохранить его в состоянии. Это позволит вам использовать его в любом компоненте, подключенном к Redux.
Кроме того, с Redux вы можете использовать промежуточное ПО Redux Thunk (или подобное), которое позволит вам использовать действия Redux для вызова API. Таким образом, вы могли бы просто написать различные вызовы API как действия Redux, которые позволили бы вам вызывать их из любого компонента и добавлять результаты в ваше хранилище Redux (которое, опять же, может использоваться в любом компоненте, подключенном к Redux).
Так, например, ваша функция getNowPlaying() может быть действием, выглядящим примерно так:
function getNowPlaying() {
return function (dispatch, getState) {
// get the token and init the api
const access_token = getState().spotify.access_token
spotifyWebApi.setAccessToken(access_token)
return spotifyWebApi.getMyCurrentPlaybackState().then((response) => {
dispatch({
type: 'SET_NOW_PLAYING',
name: response.item.name,
image: response.item.album.images[0].url
})
})
}
}
Примечание. Вам необходимо настроить Редукс-редуктор для «spotify» (или, как вы хотите, структурировать свой магазин) для хранения необходимых данных.
Итак, вы можете вызвать getNowPlaying () из любого компонента. Он сохраняет результаты в хранилище redux, которое вы также можете использовать из любого подключенного компонента. И вы можете использовать ту же технику получения access_token из магазина, когда это необходимо в действиях.
В качестве альтернативы, если вы не хотите использовать Redux, вы можете предоставить значения контекста всем дочерним компонентам, используя функции Контекст React. Вы можете сделать это с помощью того токена, который понадобится каждому компоненту в вашей настройке. Но, на мой взгляд, Redux - лучший вариант для вас.
Спасибо! Разве const access_token = getState().spotify.access_token не лишний? Разве я не могу просто использовать spotifyWebApi.setAccessToken(getState().spotify.access_token). Зачем мне резервировать для этого память?
Да, я просто пытался прояснить, что я там делал, но вы также можете сделать это с помощью этого однострочника. Рад, что помог!
как мне получить новое имя и изображение из внешнего презентационного компонента? idk, если необходимо создать образ connect и имя для компонента и обработать действие отправки с помощью редуктора. Как использовать имя и изображение внутри компонента?
Если это презентационный компонент, который вы хотите сохранить «немым», возьмите их в родительском «умном» или подключенном компоненте и передайте их в качестве свойств дочернему компоненту. Но если презентационный компонент стоит сам по себе, а не входит в список компонентов, которые будут часто обновляться, вы можете просто подключить его напрямую. Просто знайте, что подключенный компонент будет обновляться и повторно отображаться, если те поля состояния, которые вы сопоставили, изменятся. Надеюсь, я понял это и помог.
Спасибо! Но ... что такое
!!token?