【问题标题】:call mapDispatchToProps inside axios success not working在axios成功中调用mapDispatchToProps不起作用
【发布时间】:2018-09-12 06:00:37
【问题描述】:

在成功调用 axios 后,我试图导航到另一个页面,该调用调度操作以更改状态。但是,我确信我在 axios 调用中错误地调用了调度,导致以下错误。我尝试了许多其他方法,例如使用 ES6 箭头函数来调用调度方法,但都无法正常工作。

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

App.js

import React, { Component } from 'react';
import axios from 'axios';
import history from './History';
import { Redirect } from "react-router-dom";
import './App.css';
import { connect } from 'react-redux';
import * as actionType from './reducer/action';

class App extends Component {

constructor(){
    super();
    this.state = {
        username: '',
        password: '',
        loginData: []
    };

  this.handleUserChange = this.handleUserChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
}


handleSubmit(event){
    event.preventDefault();
    axios.post('https://api.github.com/user',{}, {
      auth: {
        username: this.state.username,
        password: this.state.password
      }
    }).then((response) => {
      console.log(response.data);
      this.props.onLoginAuth(true);// This is where i am getting ERROR
      //history.push({pathname: '/home', state: { detail: response.data }});
      //history.go('/home');
      this.setState({
        loginData : response.data,
      });
    }).catch(function(error) {
      console.log('Error on Authentication' + error);
  });
}

handleUserChange(event){
    this.setState({
      username : event.target.value,
    });
}

handlePasswordChange = event => {
  this.setState({
    password: event.target.value
  });
}



render() {
    if(this.props.authenticated){
      console.log("Redirecting to Home page " + this.props.authenticated);
      return <Redirect to={{ pathname: '/home', state: { detail: this.state.loginData } }}/>
    }
    return (
      <div className='loginForm'>
        <form onSubmit={this.handleSubmit}>
          <label>
            username :
            <input type="text" value={this.state.username} onChange={this.handleUserChange} required/>
          </label>
          <label>
            password :
            <input type="password" value={this.state.password} onChange={this.handlePasswordChange} required/>
          </label>
          <input type="submit" value="LogIn" />
        </form>
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    authenticated: state.authenticated
  };
}

const mapDispatchToProps = dispatch => {
  return {
    onLoginAuth: (authenticated) => dispatch({type: actionType.AUTH_LOGIN, authenticated:authenticated})
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(App);

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import PrivateRoute from './PrivateRoute';
import { Provider } from 'react-redux';
import { createStore } from 'redux';

import {
  Router,
  Redirect,
  Route,
  Switch
} from "react-router-dom";
import Home from './Home';
import User from './User';
import history from './History';
import reducer from './reducer/Login';

const store = createStore(reducer);

ReactDOM.render(
<Provider store= {store} >
  <Router history={history}>
    <Switch>
      <Route path="/" exact component={App} />
      <PrivateRoute path="/home" component={Home} />
      <PrivateRoute path="/user" component={User} />
   </Switch>
  </Router>
</Provider>,
  document.getElementById('root'));
registerServiceWorker();

Home.js

import React, { Component } from 'react';
import axios from 'axios';
import Autosuggest from 'react-autosuggest';
import './Home.css';
import history from './History';


// When suggestion is clicked, Autosuggest needs to populate the input
// based on the clicked suggestion. Teach Autosuggest how to calculate the
// input value for every given suggestion.
const getSuggestionValue = suggestion => suggestion;

// Use your imagination to render suggestions.
const renderSuggestion = suggestion => (
  <div>
    {suggestion}
  </div>
);

class Home extends Component {
  constructor(props) {
    super(props);

    // Autosuggest is a controlled component.
    // This means that you need to provide an input value
    // and an onChange handler that updates this value (see below).
    // Suggestions also need to be provided to the Autosuggest,
    // and they are initially empty because the Autosuggest is closed.
    this.state = {
      value: '',
      suggestions: [],
      timeout: 0
    };
  }

  onChange = (event, { newValue }) => {
    this.setState({
      value: newValue
    });
   console.log('=====++++ ' + newValue);
  };

  onSuggestionSelected = (event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }) => {
    console.log("Get the user +++++++++ " + suggestionValue);
   if(suggestionValue && suggestionValue.length >= 1){
       axios.get('https://api.github.com/users/'+ suggestionValue)
       .then((response) => {
          console.log("user selected : "+ response.data.avatar_url);
          history.push({pathname: '/user', state: { detail: response.data }});
          history.go('/user');
       }).catch(function(error) {
          console.log('Error on Authentication' + error);
        });
     }
  };

  // Autosuggest will call this function every time you need to update suggestions.
  // You already implemented this logic above, so just use it.
  onSuggestionsFetchRequested = ({ value }) => {
    if(this.timeout) clearTimeout(this.timeout);
    this.timeout = setTimeout(() => {
        this.getSuggestions();
      }, 500);
  };

getSuggestions = () =>{
  if(this.state.value && this.state.value.length >= 1){
  axios.get('https://api.github.com/search/users',{
    params: {
      q: this.state.value,
      in:'login',
      type:'Users'
    }
  }).then((response) => {
      console.log("users login : "+ response.data.items);
      const userNames = response.data.items.map(item => item.login);
      console.log("===== " + userNames);
        this.setState({
          suggestions: userNames
        })
  }).catch(function(error) {
    console.log('Error on Authentication' + error);
   });
 }
};

  // Autosuggest will call this function every time you need to clear suggestions.
  onSuggestionsClearRequested = () => {
    this.setState({
      suggestions: []
    });
  };


  render(){

    const { value, suggestions } = this.state;

    // Autosuggest will pass through all these props to the input.
    const inputProps = {
      placeholder: 'Type a userName',
      value,
      onChange: this.onChange
    };

    return (
      <div>
      <div>
        Home page {this.props.location.state.detail.login}
      </div>
      <div>
          <Autosuggest
            suggestions={suggestions}
            onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
            onSuggestionsClearRequested={this.onSuggestionsClearRequested}
            getSuggestionValue={getSuggestionValue}
            renderSuggestion={renderSuggestion}
            inputProps={inputProps}
            onSuggestionSelected={this.onSuggestionSelected}
          />
      </div>
    </div>
    );
}
}

export default Home;

PrivateRouter.js

import React from 'react';
import {
  Redirect,
  Route,
  } from "react-router-dom";



const PrivateRoute = ({ component: Component, ...rest}) => (
  <Route
    {...rest}
    render={props =>
      props.authenticated ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);
export default PrivateRoute;

你能帮我如何从 axios 调用 onLoginAuth 吗?

【问题讨论】:

  • 你能显示你的路线配置吗?
  • 用路由配置更新了帖子。
  • 在这里无法检测到问题 :( 需要查看HomePrivateRoute 的代码。理想情况下,对于这样的问题,可以考虑创建一个codesandbox.io/s/new,以证明您的问题.
  • 目前,您可以尝试在设置loginData 后调用您的onLoginAuththis.setState({ loginData : response.data }, () =&gt; this.props.onLoginAuth(true));
  • 出现错误前您在控制台中看到的最后一个log 是什么?

标签: javascript reactjs react-redux


【解决方案1】:

我认为问题不在于 axios 调用。您的 axios 调用更新状态 authenticated 的调度。所以每次authenticated状态更新,App组件的render方法都会被调用。

条件if(this.props.authenticated)得到验证,调用Redirect/home。但不知何故,您的路由器再次路由到 /App 组件正在重新呈现。条件if(this.props.authenticated) 再次为真,并且路由再次路由到 App。 它会创建一个无限循环,这就是为什么您会看到消息Maximum update depth exceeded

index.js中,出于测试目的,将所有PrivateRoute替换为Route,看看路由是否正常。如果有效,则问题可能来自您的 PrivateRoute 组件。

【讨论】:

  • 是的,它可以工作,但有警告。我会尝试修复它们
  • 所以问题出在 PrivateRoute 组件上。检查此组件或在此处发布。
猜你喜欢
  • 2013-03-06
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多