Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ReactJS-componentDidUpdate()必须在一个操作之前更新两个值_Reactjs_Axios - Fatal编程技术网

ReactJS-componentDidUpdate()必须在一个操作之前更新两个值

ReactJS-componentDidUpdate()必须在一个操作之前更新两个值,reactjs,axios,Reactjs,Axios,在我的ReactJS组件中,我对外部API执行一个令牌请求,然后必须将该令牌以及我的用户ID作为参数传递给axios请求。这是我的代码: import React, { Component } from 'react'; import axios from 'axios'; import Credentials from './spotify-auth.js' import './Spotify.css' class SpotifyAuth extends Component { c

在我的ReactJS组件中,我对外部API执行一个令牌请求,然后必须将该令牌以及我的用户ID作为参数传递给
axios
请求。这是我的代码:

import React, { Component } from 'react';
import axios from 'axios';
import Credentials from './spotify-auth.js'
import './Spotify.css'


class SpotifyAuth extends Component {  
  constructor (props) {
    super(props);
    this.state = {
      isAuthenticatedWithSpotify: false,
      menu: this.props.userId.menu
    };
    this.state.handleRedirect = this.handleRedirect.bind(this);
  };

  componentDidUpdate() {
      this.getFeatures(); // <------- axios method, see below
  }

  generateRandomString(length) {
    let text = '';
    const possible =
      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    for (let i = 0; i < length; i++) {
      text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
    } 

  getHashParams() {
    const hashParams = {};
    const r = /([^&;=]+)=?([^&;]*)/g;
    const q = window.location.hash.substring(1);
    let e = r.exec(q);
    while (e) {
      hashParams[e[1]] = decodeURIComponent(e[2]);
      e = r.exec(q);
    }
    return hashParams;
  }

  componentDidMount() {
    //if (this.props.isAuthenticated) {
    const params = this.getHashParams();

    const access_token = params.access_token;
    const state = params.state;
    const storedState = localStorage.getItem(Credentials.stateKey);
    localStorage.setItem('spotifyAuthToken', access_token);
    localStorage.getItem('spotifyAuthToken');

    if (window.localStorage.getItem('authToken')) {
      this.setState({ isAuthenticatedWithSpotify: true });
    };
    if (access_token && (state == null || state !== storedState)) {
      alert('Click "ok" to finish authentication with Spotify');
    } else {
      localStorage.removeItem(Credentials.stateKey);
    }
    // DO STUFF WITH ACCEES TOKEN HERE
    this.props.onConnectWithSpotify(access_token); 
  };
现在,我没有收到使用未定义值的错误调用,但是axios方法被调用了两次,每次值更新一次,这也是不希望的


如果我将
getFeatures()
放入
componentdiddupdate()
中,并且不使用条件,我会得到:

  • 两个值都未定义的请求失败
  • 然后它更新了
    userId
    ,我只得到了
    spotifyToken
    的未定义
  • 最后,当我单击按钮时,两个值都会更新,但请求会发送两次。
  • 根据单一责任原则,我还尝试了以下解决方案:

      getFeatures(event) {
        const {userId, spotifyToken} = this.props
        if (!spotifyToken || !userId) {   // <-------------- HERE
          return;
        }
        const data = {
          spotify_token: this.props.spotifyToken
        };
        var headers = {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': true,
            Authorization: `Bearer ${window.localStorage.authToken}`
          }
        const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/features/${userId}/${spotifyToken}`;
        axios.post(url, data, {headers: headers})
          .then((res) => {
            console.log(data);
          })
          .catch((err) => {
          });
      };
    
      handleRedirect(event) {
        event.preventDefault()
        this.props.createMessage('You linked your Spotify account!', 'success');
        // get client features at authentication
        const params = this.getHashParams();
        const access_token = params.access_token;
        console.log(access_token);
    
        const state = this.generateRandomString(16);
        localStorage.setItem(Credentials.stateKey, state);
    
        let url = 'https://accounts.spotify.com/authorize';
        url += '?response_type=token';
        url += '&client_id=' + encodeURIComponent(Credentials.client_id);
        url += '&scope=' + encodeURIComponent(Credentials.scope);
        url += '&redirect_uri=' + encodeURIComponent(Credentials.redirect_uri);
        url += '&state=' + encodeURIComponent(state);
        window.location = url; 
      };
    
      render() {
          return (
            <div className="button_container">
            <h1 className="title is-3"><font color="#C86428">{"Welcome"}</font></h1>
                <div className="Line" /><br/>
                  <button className="sp_button" onClick={(event) => this.handleRedirect(event)}>
                    <strong>LINK YOUR SPOTIFY ACCOUNT</strong>
                  </button>
            </div>
          )
      }
    }
    export default SpotifyAuth;
    
    但它不起作用



    如何解决此问题?

    您不能将axios请求放入componentDidMount,只需确保检查令牌和用户id是否存在?当您执行重定向(window.location=url)时,应该会卸载组件,对吗?它们确实存在,但axios请求是预先调用的。是的,我想它会卸载组件。我会把我的想法放在一个答案中,因为这里很难放代码。当然可以,谢谢。如果我把
    getFeatures()
    放在
    componentdiddupdate()
    里面,并且不使用条件,我会收到一个失败的请求,其中两个值都未定义,然后它更新
    userId
    ,并仅为令牌抛出未定义。最后,当我点击按钮时,它会工作,但随后请求会被发送两次。
    componentDidUpdate(prevProps) {
      const { spotifyToken, userId } = this.props;
      if (spotifyToken && userId && (spotifyToken !== prevProps.spotifyToken || userId !== prevProps.userId)) {
        this.getFeatures();
      }
    }