Reputation: 185
I am trying to write an application in react, and I faced the issue of having to manage the state for so many components, so I wanted to use redux. From what I read, Redux doesn't work on the root component, so I created an intermediate component named it "wrapper" that will wrap everything and manage the state of my application. So now I have my original root component and a wrapper component. I am trying to get some props in this wrapper component using redux, but the props aren't populated for some reason and I can't figure it out.
Here's my code:
import * as React from 'react'
import { Provider } from "react-redux";
import { connect } from "react-redux";
//SPFX references
import { DefaultButton, IButtonProps } from 'office-ui-fabric-react/lib/Button';
import { Panel, PanelType } from 'office-ui-fabric-react/lib/Panel';
//custom references
import { IRootProps } from '../props/IRootProps'
import { IRootState } from '../states/IRootState'
import { ITile, ITileHeader, ITileItem } from '../props/ITileStructure'
import store from '../main/store'
import { openPanel, closePanel } from '../actions/panelAction'
//Styles references
import rootStyles from '../styles/RooComponent.module.scss'
import commonStyles from '../styles/common.module.scss'
//Components references
import PanelComponent from './PanelComponent'
import FooterComponent from './FooterComponent'
import DiscardChangesDialogComponent from './DiscardChangesDialogComponent'
import BladesRootComponent from './BladesRootComponent'
import TilesListComponent from './TilesListComponent'
class RootComponent extends React.Component<{}, {}>{
tiles: ITile[] = [];
constructor(props) {
super(props);
}
render(): JSX.Element {
return (
<Provider store={store}>
<AppWrapper />
</Provider>
)
}
}
class AppWrapper extends React.Component<IRootProps, IRootState>{
tiles: ITile[] = [];
constructor(props: IRootProps) {
super(props);
if (this.tiles.length === 0) {
for (let i = 0; i < 200; i++) {
this.tiles.push({
key: i,
tileName: 'tile ' + i,
tileImageUrl: 'image url ' + i,
tileOrder: i,
headers: []
});
}
}
}
render(): JSX.Element {
return (
<div className="RootComponent">
<DefaultButton onClick={() => this.props.panelProps.openPanel()} className={commonStyles.defaultButton} >Configure Tiles</DefaultButton>
<Panel
isOpen={this.props.panelProps.isPanelOpen}
// tslint:disable-next-line:jsx-no-lambda
onDismiss={() => {
this.setState({ showPanel: false })
}}
type={PanelType.extraLarge}
headerText="Tiles configuration"
hasCloseButton={false}>
<PanelComponent />
</Panel>
</div>
)
}
}
let mapStateToProps = (state) => {
return {
panelProps: state.panel,
};
};
let mapDispatchToProps = (dispatch) => {
return {
openPanel: () => {
dispatch(openPanel());
}
};
};
connect(mapStateToProps, mapDispatchToProps)(AppWrapper);
export default RootComponent;
This is the code for the ../main/store:
import {createStore, combineReducers} from 'redux';
import {Store} from 'redux';
import panel from "../reducers/panelReducer";
let store = createStore(
combineReducers({
panel
}),
{}
);
export default store;
and ../reducers/panelReduce looks like this:
//(state, action) =>
const panelReducer = (state = {
isPanelOpen: false
}, action) => {
switch (action.type) {
case "OPEN_PANEL":
state = {
...state,
isPanelOpen: true
};
break;
case "CLOSE_PANEL":
state = {
...state,
isPanelOpen: false
};
break;
}
return state;
};
export default panelReducer;
However, the code is getting executed and at the line : <Panel
isOpen={this.props.panelProps.isPanelOpen}
it's telling me cannot access isPanelOpen of undefined. For some reason Redux isn't connected the right way.
P.S I am still a beginner in Redux so I might be doing things wrong, if anyone can point me to the right direction.
Upvotes: 0
Views: 815
Reputation: 18113
In fact you didn't use the connected AppWrapper
component inside your RootComponent
You can create a constant AppWrapperConnected : const AppWrapperConnected = connect(mapStateToProps, mapDispatchToProps)(AppWrapper);
and use <AppWrapperConnected/>
inside the RootComponent
Moreover I think it will be easier to maintain if you split RooComponent
and AppWrapper
in two separate files
Another advice is to rewrite mapStateToProps
like this
let mapStateToProps = (state) => state.panel
so you can directly use this.props.isPanelOpen
, I think panelProps
is useless here
Upvotes: 2