首页 > 解决方案 > Reactjs - 未捕获的类型错误:无法读取未定义的属性“then”

问题描述

我在这里有一个问题:当我尝试在 componentDidMount 中使用此代码时,我总是收到此错误:未捕获的 TypeError:无法读取未定义的属性 'then'

这是发生错误的组件的代码:components/Portfolio.jsx

import React, { Component } from 'react'
import Header from './Header'
import { connect } from 'react-redux';
import { auth } from '../actions';
import Popup from 'reactjs-popup';
import { portfolio } from '../actions'
import thunk from 'redux-thunk'

class Portfolio extends Component {

  state = {
    coin: undefined,
    quantity: undefined,
    buy_price: undefined,
    coindata: undefined,
    isLoaded: undefined,
  } 

    componentDidMount(){
        // this.props.fetchPortfolio();
        //   this.fetchCoins();
      this.props.fetchPortfolio().then(() => {
      this.fetchCoins();
      });
    }

  componentDidUpdate(prevProps) {
    if(this.props.auth.user !== prevProps.auth.user) {
      this.fetchCoins();
    }
  }


  submitInvestment = (e) => {
    e.preventDefault();
    this.props.addInvestment(this.state.coin, this.state.quantity,             this.state.buy_price);
    this.props.fetchPortfolio();
    this.fetchCoins();
  }


  fetchCoins(){

    let coins = this.props.portfolio.map(coin => coin.coin).join(",");
    console.log(coins);
    //console.log(coins)
    fetch("https://min-api.cryptocompare.com/data/pricemultifull?    fsyms="+coins+"&tsyms=USD")
        .then(res => res.json())
        .then(
          (result) => {
            console.log(result)
            this.setState({
              isLoaded: true,
              coindata: result,
            })
          },
          (error) => {
            this.setState({
              isLoaded: true,
              error
            });
          }
        )

  }



  render() {
    ...
   }
  }
}

const mapStateToProps = state => {
    let errors = [];
    if (state.portfolio.errors) {
        errors = Object.keys(state.portfolio.errors).map(field => {
            return {field, message: state.portfolio.errors[field]};
        });
    }
    return {
      user: state.auth.user,
      auth: state.auth,
      portfolio: state.portfolio.portfolio,
      portfolioLoaded: state.portfolio.portfolioLoaded,
      coin_symbol: state.coin,
      errors
      // errors
    }
}

const mapDispatchToProps = dispatch => {
    return {
        addInvestment: (coin, quantity, buy_price) => {
          return dispatch(portfolio.addInvestment(coin, quantity, buy_price));
        },
        deleteInvestment: (coin) => {
          dispatch(portfolio.deleteInvestment(coin));
        },
        fetchPortfolio: () => {
          dispatch(portfolio.fetchPortfolio());
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Portfolio); //

这是 actions/portfolio.js 中的 fetchPortfolio 函数:

export const fetchPortfolio = () => {
  return (dispatch, getState) => {
    let headers = {'Content-Type': 'application/json'}
    let {token} = getState().auth

    if (token) {
      headers['Authorization'] = `Token ${token}`
    }

    return fetch('/api/coins/', {headers })
      .then(res => {
        if (res.status < 500) {
          return res.json().then(data => {
            return {status: res.status, data}
          })
        } else {
          console.log('Server Error!')
          throw res
        }
      })
      .then(res => {
        if (res.status === 200) {
          dispatch({type: 'FETCH_PORTFOLIO', portfolio: res.data})
        } else if (res.status === 401 || res.status === 403) {
          dispatch({type: 'AUTHENTICATION_ERROR', data: res.data})
          throw res.data
        }
      })
  }
}

这是 App.js 代码:

import React, { Component } from 'react'

import {Switch, Route, BrowserRouter, Redirect, Link} from 'react-router-dom'
import { Provider, connect } from 'react-redux'
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'

import {auth} from './actions'
import rootReducer from './reducers'

import News from './components/News'
import NotFound from './components/NotFound'
import Login from './components/Login'
import Register from './components/Register'
import Market from './components/Market'
import Portfolio from './components/Portfolio'

let store = createStore(rootReducer, applyMiddleware(thunk))

class RootContainerComponent extends Component {
  componentDidMount () {
    this.props.loadUser()
  }

  render () {
    if (this.props.auth.isLoading) {
      return <p>Loading..</p>
    } else {
      return (
        <BrowserRouter>
          <Switch>
            <Route exact path='/' component={News} />
            <Route exact path='/login' component={Login} />
            <Route exact path='/register' component={Register} />
            <Route exact path='/markets' component={Market} />
            <Route exact path='/portfolio' component={Portfolio} />
            <Route component={NotFound} />
          </Switch>
        </BrowserRouter>
      )
    }
  }
}

const mapStateToProps = state => {
  return {
    auth: state.auth
  }
}

const mapDispatchToProps = dispatch => {
  return {
    loadUser: () => {
      return dispatch(auth.loadUser())
    }
  }    
}

let RootContainer = connect(mapStateToProps, mapDispatchToProps)        (RootContainerComponent)

export default class App extends Component {
  render () {
    return (
      <Provider store={store}>
        <RootContainer />
      </Provider>
    )
  }
}

我希望你能帮我解决这个问题!

标签: javascriptreactjs

解决方案


mapDispatchToProps你的fetchPortfolio不返回承诺或其他任何东西。您必须在其中返回一个承诺,但dispatch不返回任何东西。

你必须等待你的道具被更新mapStateToProps

你有portfolioLoaded哪个映射到你的道具。只需检查他在你的价值componentWillReceiveProps,如果它是真的,现在你可以打电话this.fetchCoins


推荐阅读