I'm using a base class for some components. However when using redux I get an issue with connect. This only happens when trying to use connect with the base class 'DockerWindow'. If I only use it on a child 'DockChat' it works. How can I access the 'store' on 'DockerWindow' (a base class)?
-> DockChat
-> DockOnline
Error:
connect.js?243b:129Uncaught TypeError: Cannot read property 'store' of undefined
Packages: React 15.0.2, React-Redux 4.4.5, Redux 3.5.2
// index.js
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import configureStore from './store/configureStore'
import Docker from './containers/Docker.js'
import './styles/docker.scss';
var dockerElement = document.querySelector('Docker');
var sessionKey = dockerElement.dataset.sessionKey || '';
var version = dockerElement.dataset.version || '0.0.1';
const store = configureStore({},version);
render(
<Provider store={store}>
<Docker session={sessionKey} />
</Provider>,
dockerElement
);
// configureStore.js
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import * as storage from 'redux-storage'
import createEngine from 'redux-storage-engine-localstorage';
import rootReducer from '../reducers';
import {mapDispatchToProps} from '../actions';
export default function configureStore(initialState,version) {
const reducer = storage.reducer(combineReducers(rootReducer));
const engine = createEngine('mytest');
const middleware = storage.createMiddleware(engine);
let store = createStore(reducer,initialState, compose(applyMiddleware(middleware)));
const load = storage.createLoader(engine);
return store;
}
// actions
export const APP_UPDATE_VERSION = 'APP_UPDATE_VERSION';
export function appUpdateVersion(version) {
return {
type: APP_UPDATE_VERSION,
version: version
}
}
export function mapDispatchToProps(dispatch) {
return {
appUpdateVersion: (version) => { dispatch(appUpdateVersion(version)); }
};
}
// reducers.
import {
APP_UPDATE_VERSION } from '../actions'
const initialStateApp = {
version:"0.0.1"
};
export function app(state = initialStateApp, action) {
switch (action.type) {
case APP_UPDATE_VERSION:
// Somehow clear engine/all states
return state;
default:
return state;
}
}
const rootReducer = {
app
};
export default rootReducer;
export function mapStateToProps(state) {
return {
app: state.app
}
}
// DockerWindow.js
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { mapDispatchToProps } from '../actions'
import {聽mapStateToProps }聽from '../reducers'
class DockerWindow extends React.Component {
constructor(props) {
super(props);
}
render(body) {
return <div>{body}</div>
}
}
export default connect(mapStateToProps,mapDispatchToProps)(DockerWindow);
// DockOnline.js
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { mapDispatchToProps } from '../actions'
import {聽mapStateToProps }聽from '../reducers'
import DockerWindow from './DockerWindow';
class DockOnline extends DockerWindow {
constructor(props) {
super(props);
}
render(){
return super.render(<div>child</div>)
}
}
export default connect(mapStateToProps,mapDispatchToProps)(DockOnline);
Finally after hours of trying it works.
For 'base class' use contextTypes only
DockerWindow.contextTypes = {
store: PropTypes.object
};
export default (DockerWindow);
and in children use connect
DockOnline.contextTypes = {
store: PropTypes.object
};
export default connect(mapStateToProps,mapDispatchToProps)(DockOnline);
Please don鈥檛 use inheritance with React. It is actively discouraged.
Rather than do
class DockOnline extends DockerWindow {
render(){
return super.render(<div>child</div>)
}
}
you should do something like
class DockOnline extends React.Component {
render(){
return (
<DockerWindow>
<div>child</div>
</DockerWindow>
);
}
}
and then use this.props.children inside DockerWindow.
Thanks for that gaeron, as a dev I've had some issues understanding how to extend classes. Now finally it all makes sense 馃憤
@gaearon Why is it discouraged to use inheritance? especially if many components are gonna be reusing same functionality and props from the base class?
Most helpful comment
Please don鈥檛 use inheritance with React. It is actively discouraged.
Rather than do
you should do something like
and then use
this.props.childreninsideDockerWindow.