Add 2 HOC to a component in react - reactjs

I have a class component in a react js app, that I want it to use router and translation.
interface CommonHeaderProps extends RouteComponentProps<any> {
}
class CommonHeader extends React.Component<CommonHeaderProps> {
render() {
return (
<div>
</div>
);
}
}
const mapStateToProps = (state: RootState) => ({
})
const mapDispatchToProps = {};
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps
)(CommonHeader));
I would like this component to have be
withRouter()(Component)
and
withTransaltion()(Component)
but doing this do not work
export default withTranslation()(withRouter(connect(
mapStateToProps,
mapDispatchToProps
)(CommonHeader)));

You can do it as this
const Component = withRouter(connect(mapStateToProps,mapDispatchToProps(CommonHeader));
export default withTransaltion()(Component)
Or you can use compose from Redux as
import { compose } from 'redux'
const Component =
withRouter(connect(mapStateToProps,mapDispatchToProps(CommonHeader));
export default compose(
withTransaltion,
withRouter,
)(Component)
Hope it helps

Related

Notistack - withRouter and withSnackbar - How?

How do I combine the withSnackbar with withRouter?
const mapStateToProps = (state, props) => {
return {
loggedIn: state.loginReducer.loggedIn
};
};
export default withRouter(connect(mapStateToProps, null)(DbPaper));
THIS DOES NOT WORK
export default withRouter(withSnackbar(DbPaper), connect(mapStateToProps, null)(DbPaper));
any help is appreciated. Thanks
compose from redux allowed me to add multiple items.
import { compose } from "redux";
export default compose(
withRouter,
withSnackbar,
connect(mapStateToProps, null)
)(DbPaper);

JSX element type 'CommonHeader' does not have any construct or call signatures

I am trying to combine multiple HOC in my react app :
Basically :
const { Header } = Layout;
interface CommonHeaderProps extends RouteComponentProps<any> {
t: Function
}
class CommonHeader extends React.Component<CommonHeaderProps> {
render() {
return (
<div>
</div>
);
}
}
const mapStateToProps = (state: RootState) => ({
})
const mapDispatchToProps = {
};
const Component = connect(
mapStateToProps,
mapDispatchToProps
)(CommonHeader)
export default compose<CommonHeader>(
withTranslation,
withRouter,
)(Component)
The problem I face is, when I try to call this component from another one in their renderer function, I have the following error
JSX element type 'CommonHeader' does not have any construct or call signatures.

React/Redux export default connect() doesn't seem to be connected to Provider

[Solved] Check my answers
I'm learning MERN Stack via a youtube playlist https://www.youtube.com/watch?v=TO6akRGXhx8. I'm stuck when i reached the 28:04 where he forgot to connect his component with 'react-redux'. I followed how he resolve it but well, for some reason mine doesn't seem to be connected. No props was pass by to my ItemModal component. So i spent 3hrs to debug and lastly conclude that i found it weird that only when the js is named ShippingList, will connect() works... When I renamed ShippingList to another name and update the references, it doesn't work anymore... Please refer to below for some of the snippet
I dont think i need to identify a component to the store when creating it.. so im stupefied now..
Was wondering if u guys can replicate it, please find my repo
https://github.com/AmeDin/mern
ShoppingList.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
export class ShoppingList extends Component {
render() {
console.log(this.props)
console.log(this.state)
//const { items } = this.props.item;
return (
<div>
</div>
)
}
}
const mapStateToProps = (state) => ({
item: state.item
})
export default connect()(ShoppingList);
ShoppingListOne.js
import React, { Component } from 'react'
import { connect } from 'react-redux';
export class ShoppingListOne extends Component {
render() {
console.log(this.props)
console.log(this.state)
//const { items } = this.props.item;
return (
<div>
</div>
)
}
}
const mapStateToProps = (state) => ({
item: state.item
})
export default connect()(ShoppingListOne);
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore, applyMiddleware, compose } from 'redux'
import rootReducer from './reducers/index'
import thunk from 'redux-thunk'
import { Provider } from 'react-redux'
import * as serviceWorker from './serviceWorker';
const middleware = [thunk];
const store = createStore(rootReducer,
compose(
applyMiddleware(thunk)
)
);
ReactDOM.render(<Provider store={store}><App /></Provider>,
document.getElementById('root'));
serviceWorker.unregister();
Screenshot of console.log: https://i.stack.imgur.com/FPBBs.png
Further testing
ShoppingListOne
const mapStateToProps = (state) => ({
item: state.item
})
const mapDispatchToProps = (dispatch) => {
console.log(dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(ShoppingListOne);
ShoppingList
const mapStateToProps = (state) => ({
item: state.item
})
const mapDispatchToProps = (dispatch) => {
console.log(dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(ShoppingList);
No functions seems to be called for ShoppingListOne.
ShoppingList has a function called line26, 3rd row of console.
https://i.stack.imgur.com/WxwRm.png
You need to pass mapStateToProps function as first argument to connect in order to make these value available to the component connected to redux store
. Connect without any arguments don't do anything except make dispatch available as a prop to the connected component
const mapStateToProps = (state) => ({
item: state.item
})
export default connect(mapStateToProps)(ShoppingListOne);
and
const mapStateToProps = (state) => ({
item: state.item
})
export default connect(mapStateToProps)(ShoppingList);
Also you need to make sure that you are imported the connected component which is ShoppingListOne exported as a default export rather than a named export
You import would look like
import ShoppingListOne from './path/to/ShoppingListOne';
You must pass mapStateToProps and mapDispatchToProps to connect, so that it can create a wrapper which has access to redux store.
export default connect(mapStateToProps, mapDispatchToProps)(ShoppingList);
export default connect(mapStateToProps, mapDispatchToProps)(ShoppingListOne);
Found out the issue...
The import statement seems to play its role to the connection..
Error
import { ShoppingList } from './components/ShoppingList';
import { ItemModal } from './components/ItemModal';
Correct
import ShoppingList from './components/ShoppingList';
import ItemModal from './components/ItemModal';
Anyone know the differences? Is there a post out there answering it i wonder?

What to use for wrapping connect function only in react-redux apps?

Do I need to use HOC if I only need to change mapDispatchToProps and mapStateToProps but not change the presentational component?
For example:
export class SomeContainer extends Component {...}
const mapStateToProps = state => {
//IMPORT HERE STATE
};
const mapDispatchToProps = (dispatch, ownProps) => ({
...someFn,
//IMPORT HERE OTHER DISPATCH FN
});
And reuse it in other components by changing connectFn.
I just wrapped it up in different components
import React, {Component, PropTypes} from "react";
import SomeContainer from "./index";
export class ReuseSomeContainerA extends Component {
render() {
return (
<SomeContainer {...this.props}/>
);
}
}
const mapDispatchToProps = (dispatch, ownProps) => ({
//...customDispatchsA
});
export const enhance = connect(() => state => ({
//customPropsA
}), mapDispatchToProps);
export default enhance(ReuseSomeContainerA );
And likewise with another used SomeContainer
export class ReuseSomeContainerB extends Component {
render() {
return (
<SomeContainer {...this.props}/>
);
}
}
const mapDispatchToProps = (dispatch, ownProps) => ({
//...customDispatchsB
});
export const enhance = connect(() => state => ({
//customPropsB
}), mapDispatchToProps);
export default enhance(ReuseSomeContainerB);
In addition to these functions do not change anything.
Is there a way of more correct composition mapDispatchToProps and mapStateToProps only?
I don't see why you would need to wrap anything in these ReuseSomeContainer components.
As I understand the question, you have the component SomeContainer which expects some props (values and functions) from redux. You want those values and functions to be different in different parts of your app, but SomeContainer would do the same thing everywhere.
You would just export SomeContainer and the use it in different locations.
Component A:
const ConnectedContainerA = connect(mapStateToPropsA, mapDispatchToPropsA)(SomeContainer);
Component B:
const ConnectedContainerB = connect(mapStateToPropsB, mapDispatchToPropsB)(SomeContainer);

React-redux doesn't set mapDispatchToProps into props

Can you help to undestand why my container doesn't transfer dispatch prop saveInfo into component?
My container:
import { connect } from 'react-redux'
import AddCarWashForm from './../components/carwash/subComponents/AddCarWashForm.jsx'
import {addInfo} from './../actions'
const mapDispatchToProps = (dispatch) => {
return {
saveInfo: (info) => {
dispatch(addInfo(info))
}
}
}
const AddCarWashFormContainer = connect(
null,
mapDispatchToProps
)(AddCarWashForm)
export default AddCarWashFormContainer
Here is part of AddCarWashForm.jsx
export default class AddCarWashForm extends React.Component{
static contextTypes = {
saveInfo: React.PropTypes.func.isRequired
};
And when I execute this code, I see in console: Warning: Failed context type: Required context 'saveInfo' was not specified in 'AddCarWashForm'.
You're mapping to props, not to context. Define it as a propType instead and it'll work as you expect it.

Resources