React + Redux + Axios 在创建动作后不加载组件
Posted
技术标签:
【中文标题】React + Redux + Axios 在创建动作后不加载组件【英文标题】:React + Redux + Axios not loading component after actions is created 【发布时间】:2018-10-22 17:06:01 【问题描述】:我正在尝试使用我创建的 API,我遵循了我之前使用过的代码,但是当加载组件时,由于 json 列表为空,它显示为空列表,我可以在记录之后正在加载列表,但组件上没有刷新或任何内容。我尝试添加一个验证,即如果列表的长度为 cero,则不打印任何内容,但这会导致错误。我可以猜到中间件存在问题(我使用的是 redux-promise)。如您所见,我在应用程序定义中添加了中间件,我看不出它缺少什么任何想法?这是我的代码:
actions/index.js:
import axios from 'axios';
export const FETCH_TESTS = 'FETCH_TESTS';
const ROOT_URL = 'http://some-working-api-entry.com';
export function fetchTests()
const request = axios.get(`$ROOT_URL/tests/?format=json`);
return
type: FETCH_TESTS,
payload: request
reducers/reducer_tests.js
import FETCH_TESTS from '../actions/index';
export default function(state = [], action)
switch (action.type)
case FETCH_TESTS:
return [action.payload.data, ...state]; //ES6 syntaxis\
return state;
actions/index.js
import combineReducers from 'redux';
import TestsReducer from './reducer_tests';
const rootReducer = combineReducers(
tests: TestsReducer
);
export default rootReducer;
容器/list_tests.js
import _ from 'lodash';
import React, Component from 'react';
import connect from 'react-redux';
import fetchTests from '../actions';
class TestList extends Component
componentDidMount()
this.props.fetchTests();
renderTest()
return _.map(this.props.tests, test =>
return (
<tr key=test.id>
<td>test.id</td>
<td>test.col1</td>
<td>test.col2</td>
<td>test.col3</td>
<td>test.col4</td>
</tr>
);
);
render()
return (
<table className="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
</tr>
</thead>
<tbody>
this.renderTest()
</tbody>
</table>
);
function mapStateToProps(state)
return tests: state.tests
//export default connect(mapStateToProps)(TestList)
export default connect(mapStateToProps, fetchTests)(TestList);
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import Provider from 'react-redux';
import createStore, applyMiddleware from 'redux';
import ReduxPromise from 'redux-promise';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
ReactDOM.render(
<Provider store=createStoreWithMiddleware(reducers)>
<App />
</Provider>
, document.getElementById('root'));
package.json
"name": "someapp",
"version": "0.1.0",
"private": true,
"dependencies":
"axios": "^0.18.0",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-redux": "^5.0.7",
"react-scripts": "1.1.4",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-promise": "^0.5.3",
,
"scripts":
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
编辑: 来自动作创建者(数组包含 api 列表入口点上的唯一对象):
config: Object timeout: 0, xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", …
data: Array [ … ]
headers: Object "content-type": "application/json"
request: XMLHttpRequest readyState: 4, timeout: 0, withCredentials: false, …
状态:200 状态文本:“确定” proto:对象 …
来自减速器:
payload:[object Object]
如果我在容器上记录测试道具,首先它会记录一个空数组 [],然后它会记录一个长度为 1 的数组
【问题讨论】:
该动作是否转到reducer?您可以通过以下方式检查网络请求的输出:axios.get(
$ROOT_URL/tests/?format=json).then(result=>console.log("result:",result)||result);
你能用 axios.get 的输出和你的 reducer 中记录每个操作的 console.log 更新问题吗?
肯定没有更新,因为你对道具什么都不做?你打电话给mapStateToProps
,但不要在componentDidReceiveProps
中找到他们。您应该在此处将它们设置为您的组件状态,这将导致组件重新渲染。
【参考方案1】:
const request = axios.get(`$ROOT_URL/tests/?format=json`);
// here is your issue because axios returns promise.
像这样创建一个 doGet 方法。
export function doGet(url, onSuccess, onFailure)
return axios.get(url)
.then((response) =>
if (onSuccess)
onSuccess(response);
return response.data || ;
)
.catch((error) =>
if (onFailure)
onFailure(error);
);
然后在你的componentDidMount
上调用这个方法,比如:
doGet(
'your/api/url',
(response) => console.log('Api success callback', response),
(error) => console.log('error callback', error)
)
【讨论】:
对不起,你错了。 axios.get 返回一个 promise,应该由 redux-promise 处理。为已经是承诺的东西添加回调选项是没有意义的。 我没看错,我为所有get请求创建了一个通用的doGet方法。 我同意调用 get 函数而不是直接使用 axios(可能来自许多不同的地方)是更好的设计,但这不是当前的问题。使用 redux-promise 中间件时,为有效负载返回承诺非常适合操作 好的,我同意你的看法。【参考方案2】:您必须调用调度员来更新商店。
在containers/list_tests.js
const mapDispatchToProp = dispatch => (
fetchTests : () => dispatch(fetchTests())
)
export default connect(mapStateToProps, mapDispatchToProp )(TestList);
编辑 1:发现另一个问题。
export function fetchTests()
return axios.get(`$ROOT_URL/tests/?format=json`)
.then(res =>
return
type: FETCH_TESTS,
payload: res.data
);
【讨论】:
我认为动作绑定已经用export default connect(mapStateToProps, fetchTests)(TestList);
正确完成了不确定res.data是否有帮助,OP需要发布响应是什么以及它是否成功。
我不知道它是如何正确的 => export default connect(mapStateToProps, fetchTests)(TestList);
.... 他想更新 redux 存储。如果我们不调用dispatch
那么redux store 将如何更新?可能我没明白你的意思。 @HMR
是的,可以pass an object:如果传递了一个对象,那么它里面的每个函数都被假定为一个Redux action creator。具有相同函数名的对象,但每个动作创建者都包装在一个调度调用中以便可以直接调用它们,将被合并到组件的 props 中。以上是关于React + Redux + Axios 在创建动作后不加载组件的主要内容,如果未能解决你的问题,请参考以下文章
REACT 如何使用 Redux 和 Axios(使用 promise 中间件)发出 AJAX 请求?
使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用