所以我正在尝试学习Redux的React,到目前为止,我认为我已经能够解决使它工作所需的大部分代码,但是在将状态传递给我的过程中存在问题零件。我正在使用Visual Studio 2017的ASP.NET Core项目模板,该模板具有react和redux样板代码,他们使用了以下代码:
export default connect(
state => state.weatherForecasts,
dispatch => bindActionCreators(actionCreators, dispatch)
)(FetchData);
我尝试用自己的组件做同样的事情,像这样:
export default connect(
state => state.lecture,
dispatch => bindActionCreators(actionCreators, dispatch)
)(LectureTable);
但是当尝试访问道具的内容时,我想要获取的属性被标记为未定义。我通过Redux devtools检查了我的初始状态是否存在,但是我的组件无法看到我要传递给它的道具。奇怪的是,我只是模仿了样板代码,但它不起作用,但样板代码工作得很好(即,我可以转到组件并注销其初始状态)。
由于我遵循的是Visual Studio使用的格式,所以我的动作创建者,化简器和常量位于以下所示的一个文件中:
const GET_LECTURES = "GET_LECTURES";
const initialState = {
lectures: [],
selectedLecture: {},
isLoading: false,
test: 0
};
export const actionCreators = {
requestLectures: isLoading => async (dispatch) =>
{
if (!isLoading) {
// Don't issue a duplicate request (we already have or are loading the requested data)
return;
}
dispatch({ type: GET_LECTURES });
const url = `api/lecture/`;
const response = await fetch(url);
const lectures = await response.json();
dispatch({ type: RECEIVE_LECTURES, payload: lectures });
}
};
export const reducer = (state = initialState, action) => {
switch (action.type) {
case GET_LECTURES:
return { ...state, isLoading: true };
default:
return state;
}
};
对不起,如果一切都很混乱。我真的才刚刚开始了解redux。
修改 我的组件代码:
import React, { Component } from 'react';
import {Button, Table, Label, Menu, Icon} from 'semantic-ui-react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import {actionCreators} from './../../store/Lecture';
export class LectureTable extends Component {
componentWillMount(){
// this.props.requestLectures(this.props.isLoading);
console.log(this.props.test);
}
render() {
return (
<Table size='large'>
{/*removed to make it cleaner..currently only has static data too lol*/}
</Table>
)
}
}
export default connect(
state => state.lecture,
dispatch => bindActionCreators(actionCreators, dispatch)
)(LectureTable);
配置我的商店的位置
import { applyMiddleware, combineReducers, compose, createStore } from 'redux';
import thunk from 'redux-thunk';
import { routerReducer, routerMiddleware } from 'react-router-redux';
import * as Lecture from './Lecture';
import * as Counter from './Counter';
import * as WeatherForecasts from './WeatherForecasts';
export default function configureStore(history, initialState) {
const reducers = {
lecture: Lecture.reducer,
counter: Counter.reducer,
weatherForecasts: WeatherForecasts.reducer
};
const middleware = [
thunk,
routerMiddleware(history)
];
// In development, use the browser's Redux dev tools extension if installed
const enhancers = [];
const isDevelopment = process.env.NODE_ENV === 'development';
if (isDevelopment && typeof window !== 'undefined' && window.devToolsExtension) {
enhancers.push(window.devToolsExtension());
}
const rootReducer = combineReducers({
...reducers,
routing: routerReducer
});
return createStore(
rootReducer,
initialState,
compose(applyMiddleware(...middleware), ...enhancers)
);
}
我的index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import { createBrowserHistory } from 'history';
import configureStore from './store/configureStore';
import App from './pages/App';
import registerServiceWorker from './registerServiceWorker';
// Create browser history to use in the Redux store
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const history = createBrowserHistory({ basename: baseUrl });
// Get the application-wide store instance, prepopulating with state from the server where available.
const initialState = window.initialReduxState;
const store = configureStore(history, initialState);
const rootElement = document.getElementById('root');
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
rootElement);
registerServiceWorker();
答案 0 :(得分:2)
connect()的第一个参数应该是一个返回对象的函数-将要添加的道具作为键,其值是state的值。例如
state => ({ lecture: state.lecture })
答案 1 :(得分:1)
在他们的示例中,我认为weatherForecasts
是一个对象。在您的示例中,lectures
似乎是一个数组,因此,如果您只需要获取mapStateToProps
属性
lectures
函数
state => ({ lectures: state.lectures})
如果您需要整个state
,则可以拥有state => state
,以便可以访问道具this.props.test
和this.props.lectures
请记住,mapStateToProps
应该返回object
,而不是array
。顺便说一下,在化简器中,字段名是lectures
(复数)而不是lecture
,所以state => state.lecture
将是undefined
答案 2 :(得分:1)
Rick,您的connect参数应该类似于:
export default connect( state => {
return {
test: state.lecture // Or any value
}
})(LectureTable);
您正在尝试控制台记录test
道具,因此您应该将其包括在连接呼叫中。
答案 3 :(得分:1)
我找到了解决方案。首先,我对堆栈溢出和反应都无知,所以我为所有不一致之处(如果是正确的词?)提出了要求。
我发现的内容:
一些注意事项:
再次编辑: 我能够将另一个子组件与Redux存储连接。我试图看看为什么我仍然无法对导致我问这个问题的特定组件执行此操作。找到原因后,我将更新答案。
答案 4 :(得分:0)
您在这里有两个问题。
您将mapStateToProps
函数定义为connect
错误的第一个参数。正如许多答案所解释的那样,现在您应该像这样使用它:
export default connect(
state => ( { lecture: state.lecture } ),
dispatch => bindActionCreators(actionCreators, dispatch)
)(LectureTable);
现在,您有一个lecture
道具作为状态。您可以使用this.props.lecture
到达它。但是,在您的componentWillMount
方法中,您尝试像this.props.test
一样记录它。应该是this.props.lecture.test
。
顺便说一句,尝试使用componentDidMount
代替componentWillMount
,因为它将在将来的版本中弃用。