【问题标题】:Action Payload returns as undefined when fetching data in Redux在 Redux 中获取数据时,Action Payload 返回未定义
【发布时间】:2019-09-14 04:38:48
【问题描述】:

我正在移植一个 React 应用程序以使用 Redux。我可以看到该操作正在触发单击事件,但是当我将 console.log 添加到减速器中的操作时,我看到了一个未定义的值。

我正在使用 Redux thunk,因为我正在使用 fetch API 获取 JSON 数据。

generateQuote 操作应该返回一个新的报价。

我做的有什么明显错误的吗?

reducers/quotes.js


const defaultState = 
{ quote: 'Hello World',
  name: 'Me',
  email: 'foo@bar.com',
  date: Date(Date.now()),
  generatedQuotes: []

 }

const quotes = (state = defaultState, action) => {
  switch(action.type) {
    case GENERATE_QUOTE : 
      console.log(action.payload)
      return { ...state, quotes: action.payload, date: action.date } 
    case DELETE_QUOTE : 
        return {
          generatedQuotes: [...state.generatedQuotes.filter(quote => quote !== action.payload)]}
    case SHARE_QUOTE : 
          return state;
    default: 
      return state;
  }
}

export default quotes;

actions/index.js

export const generateQuote = () => dispatch => {
  const randomNum = (Math.floor(Math.random() * (500 - 1)) + 1);
  fetch(`https://jsonplaceholder.typicode.com/comments?id=${randomNum.toString()}`)
  .then(res => res.json())
  .then(data => {
    return 
    dispatch( {
      type: GENERATE_QUOTE, 
      payload: data[0],
      date: Date(Date.now())
    })
  })
}

Quote.js(组件)

/* eslint-disable react/require-default-props */
/* eslint-disable react/button-has-type */
/* eslint-disable react/jsx-filename-extension */
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

const Quote = ({quote, author, email, date, generateQuote, shareQuote}) => {

  return (
    <div className="box">
      <p>
        <strong>Quote:</strong>
        {' '}
        {quote}
      </p>
      <p>
        <strong>Author:</strong>
        {' '}
        {author}
      </p>
      <p>
        <strong>Email:</strong>
        {' '}
        {email}
      </p>
      <p>
        <strong>Date:</strong>
        {' '}
        {date}
      </p>
      <br />
      <div className="buttons">
        <button className="button is-primary is-small" onClick={generateQuote}>New Quote</button>
        <button className="button is-success is-small" onClick={shareQuote}>Tweet Quote</button>
      </div>

    </div>
  );
};

Quote.propTypes = {
  quote: PropTypes.string,
  author: PropTypes.string,
  email: PropTypes.string,
  date: PropTypes.string,
  generateQuote: PropTypes.func,
  shareQuote: PropTypes.func,
};

const mapStateToProps = state => {
  const { quote, author, email, date} = state;
};

const mapDispatchToProps = dispatch => {
  return {
    generateQuote: () => dispatch({type: 'GENERATE_QUOTE'}),
    shareQuote: () => dispatch({type: 'SHARE_QUOTE'})
  };
}

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

【问题讨论】:

  • 您是否在generateQuote 操作中登录了data[0]
  • 我确实尝试过控制台日志记录data[0],但它没有返回任何内容。我想知道这是否意味着该动作实际上并未被调度?我现在才刚刚学习 Redux,所以我仍在努力掌握一切如何协同工作的窍门。
  • 这可能意味着您的 api 调用没有返回您期望的结果。
  • 这很奇怪。我使用本地状态进行了完全相同的 API 调用。如果您在这里查看 generateQuote,我会做几乎相同的事情。 github.com/fendermaniac/random-quote-machine-react/blob/master/…

标签: reactjs redux fetch redux-thunk


【解决方案1】:

我认为缺少返回语句:

export const generateQuote = () => dispatch => {
  const randomNum = (Math.floor(Math.random() * (500 - 1)) + 1);
  return fetch(`https://jsonplaceholder.typicode.com/comments?id=${randomNum.toString()}`)
  .then(res => res.json())
  .then(data => 
    dispatch({
      type: GENERATE_QUOTE, 
      payload: data[0],
      date: Date(Date.now())
  }) 
 ).catch(error => console.log(error))
}

如果错误仍然存​​在,请使用仅用于测试的静态数字尝试请求:

https://jsonplaceholder.typicode.com/comments?id=1

【讨论】:

  • 我在 fetch 之前添加了显式返回,只是测试了静态数字,但没有运气。
  • 尝试删除第二个return语句,在dispatch方法之前。我会更新代码。
  • 好的,我想我们已经到了某个地方!我现在可以看到状态正在更新,但组件没有重新渲染。我是否正在改变我的减速器中的状态?
  • 感谢 Cyro,我搞定了! mapStateToProps 似乎不喜欢解构,所以我更新了它。
  • 非常好!你也可以映射整个对象:quote: state.quote.
【解决方案2】:

看起来您需要在组件中调度您的报价操作。您将分派到您的减速器两次。一次在组件中,另一个在动作文件中。动作文件中的函数是否真的被触发了?

以下示例。

https://jsonplaceholder.typicode.com/comments?id=101 以数组响应,

[
   {
      postId: 21,
      id: 101,
      ....
   }
] 

酷。静态号码有效。您获取的逻辑是正确的。

我很好奇的是您的实际 fetch 是否被调用/解雇。在您的组件中,您调用 mapStateToProps' generateQuote 的值 => dispatch({type: 'GENERATE_QUOTE'}),就像这样...

const mapDispatchToProps = dispatch => {
  return {
    generateQuote: () => dispatch({type: 'GENERATE_QUOTE'}),
    shareQuote: () => dispatch({type: 'SHARE_QUOTE'})
  };
}

然后,您将在 actions/index.js 的 generateQuote 中再次调度它

我可能遗漏了一些东西,但你可能会一起跳过你的动作。

// ...are you sure this is firing? 
// console.log's never killed a cat. 
dispatch({
  type: GENERATE_QUOTE, 
  payload: data[0],
  date: Date(Date.now())
})

我会将您的操作放入您的 mapStateToProps() 函数中,就像这样...

import QuoteActions from '../actions"

// ... blah blah blah

const mapDispatchToProps = (dispatch) => {
  return {
    fetchProfile: (credentials) => {
      dispatch(QuoteActions.generateQuote()) // << HERE
    }
  }
}

希望这会有所帮助。

【讨论】:

  • 是的,我想知道我是否正在调用该操作。我通过像 import { generateQuote, shareQuote} from '../actions'; 这样的导入将动作添加到组件中,然后将其添加到 mapDispatchToProps const mapDispatchToProps = dispatch =&gt; { return { generateQuote: () =&gt; dispatch(generateQuote()), shareQuote: () =&gt; dispatch(shareQuote()), }; }。然后我在 action 中的 dispatch 之前添加了一个 console.log,但它似乎没有被触发。
猜你喜欢
  • 2018-08-12
  • 2021-12-01
  • 2018-03-15
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
相关资源
最近更新 更多