Как передать константу нескольким компонентам / Разделение файлов React-Redux-Router

Я создаю приложение 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
          }
        })
      })
  }
}
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
0
88
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вместо того, чтобы передавать эту константу другим компонентам, я бы создал 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'.

Спасибо! Но ... что такое !!token?

boludo kid 07.06.2018 18:36

Предполагалось, что это будет params.access_token, который был в вашем примере

Guilherme Resende Freitas 08.06.2018 20:03
Ответ принят как подходящий

В вашем заголовке упоминается 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‌​). Зачем мне резервировать для этого память?

boludo kid 07.06.2018 19:33

Да, я просто пытался прояснить, что я там делал, но вы также можете сделать это с помощью этого однострочника. Рад, что помог!

Cody Parker 07.06.2018 19:36

как мне получить новое имя и изображение из внешнего презентационного компонента? idk, если необходимо создать образ connect и имя для компонента и обработать действие отправки с помощью редуктора. Как использовать имя и изображение внутри компонента?

boludo kid 07.06.2018 23:40

Если это презентационный компонент, который вы хотите сохранить «немым», возьмите их в родительском «умном» или подключенном компоненте и передайте их в качестве свойств дочернему компоненту. Но если презентационный компонент стоит сам по себе, а не входит в список компонентов, которые будут часто обновляться, вы можете просто подключить его напрямую. Просто знайте, что подключенный компонент будет обновляться и повторно отображаться, если те поля состояния, которые вы сопоставили, изменятся. Надеюсь, я понял это и помог.

Cody Parker 08.06.2018 21:21

Другие вопросы по теме