在mapStateToProps中,它应该像访问你想要的状态部分的键一样简单,并获取状态参数,但我无法这样做。
主app.js文件
import React from 'react'
import ReactDom from 'react-dom'
import { Provider } from 'react-redux'
import { ConnectedRouter } from 'connected-react-router/immutable'
import { createBrowserHistory } from 'history'
import configureStore from './store/configureStore'
import App from './components/partials/App'
const history = createBrowserHistory()
const store = configureStore(history)
ReactDom.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App/>
</ConnectedRouter>
</Provider>,
document.getElementById('reactDiv')
)
configureStore.js
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'connected-react-router/immutable'
import thunkMiddleware from 'redux-thunk'
import { combineReducers } from 'redux-immutable'
import { connectRouter } from 'connected-react-router'
import AppReducer from './reducers/app'
const createRootReducer = history => combineReducers({
router: connectRouter(history),
app: AppReducer
})
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export default function configureStore(history) {
const middleware = [routerMiddleware(history), thunkMiddleware]
const rootReducer = createRootReducer(history)
return createStore(rootReducer, composeEnhancers(applyMiddleware(...middleware)))
}
appReducer
/**
* App level reducer
*/
const initialState = {
accounts: [],
employees: []
}
const reducer = (state = initialState, action) => {
switch(action.type) {
case 'ACCOUNT_SELECTION_LIST_LOADED':
return {...state, accounts: action.payload}
case 'EMPLOYEE_SELECTION_LIST_LOADED':
return {...state, employees: action.payload}
}
return state
}
export async function fetchAccountsSelectionList(dispatch, getState) {
makeAjaxRequest('/getList/accounts', 'GET', null, response => {
const accounts = JSON.parse(response)
dispatch({type: 'ACCOUNT_SELECTION_LIST_LOADED', payload: accounts})
})
}
export async function fetchEmployeesSelectionList(dispatch, getState) {
makeAjaxRequest('/getList/employees', 'GET', null, response => {
const employees = JSON.parse(response)
dispatch({type: 'EMPLOYEE_SELECTION_LIST_LOADED', payload: employees})
})
}
export default reducer
主要组件(缩小以节省空间)
import React, { Component } from 'react'
import { BrowserRouter, Switch, Route } from 'react-router-dom'
import { LinkContainer } from 'react-router-bootstrap'
import { FormControl, InputGroup, Navbar, Nav, NavDropdown, NavLink } from 'react-bootstrap'
import { connect } from 'react-redux'
import { fetchAccountsSelectionList, fetchEmployeesSelectionList } from '../../store/reducers/app'
import Select from 'react-select'
class App extends Component {
constructor() {
super()
this.state = {
billId: '',
invoiceId: '',
manifestId: ''
}
this.handleChange = this.handleChange.bind(this)
}
componentDidMount() {
this.props.fetchAccountsSelectionList()
this.props.fetchEmployeesSelectionList()
}
handleChange(event) {
const {name, checked, value, type} = event.target
this.setState({[name]: type === 'checkbox' ? checked : value})
}
render() {
return (
<BrowserRouter>
<Navbar variant='dark' bg='dark' className={'navbar-expand-lg', 'navbar'}>
<LinkContainer to='/'>
<Navbar.Brand>Fast Forward Express v2.0</Navbar.Brand>
</LinkContainer>
<Navbar.Toggle aria-controls='responsive-navbar-nav' />
<Navbar.Collapse id='responsive-navbar-nav'>
<Nav className='ml-auto'>
<NavDropdown title='Bills' id='navbar-bills'>
</NavDropdown>
<NavDropdown title='Invoices' id='navbar-invoices'>
</NavDropdown>
<NavDropdown title='Accounts' id='navbar-accounts' alignRight>
</NavDropdown>
<NavDropdown title='Employees' id='navbar-employees' alignRight>
</NavDropdown>
<LinkContainer to='/app/dispatch'><NavLink>Dispatch</NavLink></LinkContainer>
<NavDropdown title='Administration' id='navbar-admin' alignRight>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Navbar>
<Switch>
<Route path='xxx' component={xxx}></Route>
</Switch>
</BrowserRouter>
)
}
}
const matchDispatchToProps = dispatch => {
return {
fetchAccountsSelectionList: () => dispatch(fetchAccountsSelectionList),
fetchEmployeesSelectionList: () => dispatch(fetchEmployeesSelectionList)
}
}
const mapStateToProps = state => {
return {
accounts: state.app.accounts,
employees: state.app.employees
}
}
export default connect(mapStateToProps, matchDispatchToProps)(App)
所以。当我注销 mapStateToProps 正在接收的“状态”时,它是一个 Map,而不是一个对象,如下所示:
为什么我的状态看起来不像我看过的任何教程?我无法找到任何其他这样的示例,除了一个说只需手动迭代的示例 - 但由于这不是“正确”的方式,我必须错误地配置存储
我应该注意到,开发人员工具似乎能够完美地访问状态,并反映我期望看到的内容。为什么我无法访问 state.app.accounts
问题是您使用的两个包依赖于 Immutable.js 数据结构,而不是普通的 JS 对象:
import { combineReducers } from 'redux-immutable'
和 import { routerMiddleware } from 'connected-react-router/immutable'。
特别是,来自
combineReducers
的 redux-immutable
将导致根状态对象成为 Immutable.js Map
实例,而不是普通对象,并且 Map
实例具有 .get()
和 .set()
方法而不是普通字段。
我们强烈建议反对此时在 Redux 应用程序中使用 Immutable.js 。
相反,您应该将状态编写为纯 JS 对象和数组,并且您应该使用 我们的官方 Redux Toolkit 包来设置您的存储并编写您的减速器。
请仔细阅读 Redux 核心文档中的官方 “Redux Essentials” 和 “Redux Fundamentals” 教程,了解如何使用 Redux Toolkit 编写 Redux 逻辑。