Я пытаюсь внедрить Redux в мой проект React.Прямо сейчас у меня есть ошибка на моей первой странице, и я не могу ее исправить.Мой редуктор, хранилище, начальное состояние не определены при инициализации компонента.
Я постараюсь поместить весь важный код, если что-то отсутствует, я могу обновить вопрос.
Тип действия:
export default interface IAction<T>
{
type: string;
payload?: T;
error?: boolean;
meta?: any;
}
Корневой магазин:
import IBookingTypeState from '../pages/bookmark/home/IBookingTypeState';
import IBookingSearchState from '../pages/bookmark/search/bookingSearchState';
export default interface IStore
{
readonly bookingSearchReducer: IBookingSearchState;
}
Корневой редуктор:
import { combineReducers, Reducer, ReducersMapObject } from 'redux';
import IStore from './rootStore';
import BookingTypeReducer from './booking/bookingType/bookingTypeReducer';
import BookingSearchReducer from './booking/bookingSearch/bookingSearchReducer';
const reducerMap: ReducersMapObject =
{
bookigSeacrhReducer: BookingSearchReducer.reducer
}
export default combineReducers(reducerMap) as Reducer<IStore>;
Создатель действия:
import IAction from '../../IAction';
import IBookingSearch from './../../../models/bookingSearch';
export default class BookingSearchAction
{
public static readonly SET: string = 'BookingSearchAction.SET';
public static readonly GET: string = 'BookingSearchAction.GET';
public static setBookingsSearch(bookingSearch: IBookingSearch): IAction<IBookingSearch>
{
return {
error: false,
meta: null,
payload: bookingSearch,
type: BookingSearchAction.SET
}
}
public static getBookingsSearch(): IAction<null>
{
return {
error: false,
meta: null,
payload: null,
type: BookingSearchAction.GET
}
}
}
IBookingSearch - это просто интерфейс для хранения данных поиска.
Редуктор:
import IBookingSearch from './../../../models/bookingSearch';
import IBookingSearchState from './../../../pages/bookmark/search/bookingSearchState';
import IAction from './../../IAction';
import BookingSearchAction from './bookingSearchAction';
export default class BookingSearchReducer
{
private static readonly _initialState: IBookingSearchState =
({
searchParameters:
{
Arrival: new Date(),
Departure: new Date(),
Lenght: 0,
Beam: 0,
Draft: 0,
ShorePower: 0,
PromoCode: ''
}
});
public static reducer(state: IBookingSearchState = BookingSearchReducer._initialState, action: IAction<IBookingSearch>) : IBookingSearchState
{
switch (action.type)
{
case BookingSearchAction.SET:
return BookingSearchReducer._setBookingSearch(state, action);
case BookingSearchAction.GET:
return BookingSearchReducer._getBookingSearch(state, action);
default:
return state;
}
}
private static _setBookingSearch(state: IBookingSearchState, action: IAction<IBookingSearch>) : IBookingSearchState
{
if (!action.payload)
{
return {
...state
}
}
return {
...state,
searchParameters: action.payload
}
}
private static _getBookingSearch(state: IBookingSearchState, action: IAction<IBookingSearch>) : IBookingSearchState
{
return {
...state
}
}
}
Компонент, в котором я хочу его использовать:
interface IStateToProps extends IBookingSearchState
{}
interface IDispatchToProps
{
dispatch: (action: IAction<IBookingSearch>) => void;
}
const mapStateToProps = (state: IStore): IStateToProps =>
({
searchParameters: state.bookingSearchReducer.searchParameters
});
const mapDispatchToProps = (dispatch: Dispatch<IAction<IBookingSearch>>): IDispatchToProps =>
({
dispatch
});
class SearchFormDesktop extends React.Component<IStateToProps & IDispatchToProps & WithStyles<typeof styles> & RouteComponentProps<{}>, {}>
{
private searchParameters: IBookingSearch = (null!);
constructor(props: IStateToProps & IDispatchToProps & WithStyles<typeof styles> & RouteComponentProps<{}>)
{
super(props);
}
handleChange = (e: React.ChangeEvent<HTMLInputElement>): void =>
{
e.preventDefault();
this.searchParameters
{
[e.target.name] = e.target.value
}
}
handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>): void =>
{
e.preventDefault();
this.searchParameters
{
[e.target.name] = e.target.value
}
}
private submitHandler = () =>
{
console.log(this.state);
//dispatch state
this.props.dispatch(BookingSearchAction.setBookingsSearch(this.searchParameters));
this.props.history.push(Urls.bookingoffers);
}
render()
{
const css = this.props.classes;
const enabled = this.searchParameters &&
this.searchParameters.Arrival &&
this.searchParameters.Departure &&
this.searchParameters.Beam &&
this.searchParameters.Lenght &&
this.searchParameters.Draft
const Body = () =>
<StackPanel stretch orientation="vertical" centerVertically className = { css.root }>
<StackPanel centerHorizontally centerVertically>
<h3>Short-Term Dockage</h3>
</StackPanel>
<DockPanel {...dockBottom}>
<StackPanel {...dockLeft}>
<DatePickerWithLapbel label="Arrival" name="arrival" onChange={this.handleChange}/>
</StackPanel>
<StackPanel {...dockRight}>
<DatePickerWithLapbel label="Departure" name="departure" onChange={this.handleChange}/>
</StackPanel>
</DockPanel>
<DockPanel {...dockBottom}>
<StackPanel {...dockLeft}>
<NumericInput label="Lenght" name="Lenght" onChange={this.handleChange}/>
</StackPanel>
<StackPanel>
<NumericInput label="Beam" name="Beam" onChange={this.handleChange}/>
</StackPanel>
<StackPanel {...dockRight}>
<NumericInput label="Draft" name="Draft" onChange={this.handleChange}/>
</StackPanel>
</DockPanel>
<DockPanel {...dockBottom}>
<SelectInput {...dockLeft} label="Shore Power (optional)" name="ShorePower" onChange={this.handleSelectChange}/>
</DockPanel>
<DockPanel {...dockBottom}>
<StackPanel>
<Typography variant="subtitle1" className={css.promo}>Add promo or group code</Typography>
</StackPanel>
</DockPanel>
<DockPanel {...dockBottom}>
<StackPanel>
<Button variant="contained"
color="primary"
fullWidth={ true }
size="large"
className={css.button}
onClick = { this.submitHandler }
disabled={!enabled}
>
Check Availability
</Button>
</StackPanel>
</DockPanel>
</StackPanel>
return Body();
}
}
export default connect(mapStateToProps, mapDispatchToProps) (withRoot(withStyles(styles)(SearchFormDesktop)));
И, наконец, индекс.tsx
// create the saga middleware
const sagaMiddleware = createSagaMiddleware();
const store = createStore(Reducer, composeWithDevTools(applyMiddleware(sagaMiddleware)));
sagaMiddleware.run(rootSaga);
const container =
<Provider store={store}>
<AppContainer>
<Router history={ history }>
<IndexRoutes/>
</Router>
</AppContainer>
</Provider>
const ROOT = document.getElementById('root');
ReactDOM.render(container, ROOT);
В моем проекте я также использую Material-UI.Thnx.