Notistack - withRouter and withSnackbar - How? - reactjs

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);

Related

Add 2 HOC to a component in react

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

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?

Where to put withRouter in react

In my application, I seperated redux part from the react components. Now i'm confused with, where to put the withRouter(). It works on both component and container, but what will be the good practice?
Here is my code.
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import {bindActionCreators} from 'redux';
import RegisterScreen from './RegisterScreen';
import { registerUser } from '../../../actions';
const mapStateToProps = state => ({
auth: state.auth,
errors: state.errors
});
const mapDispatchToProps = dispatch => ({
registerUser: bindActionCreators(registerUser, dispatch)
});
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(RegisterScreen));
Here if we export like, this and set withRouter in the component, still it works. What is the better approach?
export default connect(mapStateToProps, mapDispatchToProps)(RegisterScreen)
enter code here
IMO it would be cleaner to do it in the component( v.s. its container, if it has one).
That way there can be components that are not connected to the global state(Do not have a container) which still can be wrapped with withRouter if they need its functionality.
As far as I know, the only time where it matters is when you want to access the router in ownProps in mapStateToProps.
You need to wrap the connected component in order to access the router in mapStateToProps, like this:
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps,
)(RegisterScreen));

Redux store does not have a valid reducer

Haven't been able to find anything around here regarding this error:
"Store does not have a valid reducer. Make sure the argument passed to combineReducers is an object whose values are reducers."
My reducer
export default function FriendListReducer(state = {friends : []}, action) {
switch (action.type) {
case 'ADD_FRIEND':
return [
{ friends : action.payload.friend }, ...state.friends
]
default:
return state;
}
return state;
}
Combiner
import { combineReducers } from 'redux';
import { FriendListReducer } from './FriendListReducer';
const rootReducer = combineReducers({
friends: FriendListReducer
});
export default rootReducer;
My store config
import { applyMiddleware, createStore } from 'redux';
import thunkMiddleware from 'redux-thunk';
import createLogger from 'redux-logger';
import rootReducer from '../reducers/reducers';
export default function configureStore(initialState = { friends: [] }) {
const logger = createLogger({
collapsed: true,
predicate: () =>
process.env.NODE_ENV === `development`, // eslint-disable-line no-unused-vars
});
const middleware = applyMiddleware(thunkMiddleware, logger);
const store = middleware(createStore)(rootReducer, initialState);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers/reducers', () => {
const nextRootReducer = require('../reducers/reducers').default;
store.replaceReducer(nextRootReducer);
});
}
return store;
}
Your import statement is incorrect. Either you use import { Foo } from 'bar' together with export Foo, or use import Foo from 'bar' if you export with export default Foo.
In other words, change either export default function FriendListReducer to export function FriendListReducer, or change the import statement from import { FriendListReducer } to import FriendListReducer.
If the object is empty.
export default combineReducers({
})
This error will show.
../reducers/reducers ? it's a strange naming
Anyway, it seems ../reducers/reducers doesn't return a reducer, if reducers is a directory, put a index.js inside, import each reducer and create a root reducer
import FriendListReducer from "./FriendListReducer"
const rootReducer = combineReducers({
friendList : FriendListReducer
})
export default rootReducer
Important!! you will have state.friendList in your state.
I hope it will help
store.js
FALSE
import { charactersSlice } from "./charactersSlice.js";
TRUE NOT USING {}
import charactersSlice from "./charactersSlice.js";
It looks like your top-level reducer function is using an array as its default value. Redux expects that the very top of your state will be an object, not an array. Try putting the array at a particular key in that object, like { friendList : [] }.
on above your codes
import { FriendListReducer } from './FriendListReducer';
const rootReducer = combineReducers({
friends: FriendListReducer
});
export default rootReducer;
instead of import { FriendListReducer } from './FriendListReducer';
just say import FriendListReducer from './FriendListReducer';
since FriendListReducer was exported with export default FriendListReducer and not export const FriendListReducer
Please check your combine reducer file It's empty......
you have forgot bind reducer here
import {combineReducers, createStore} from 'redux'
import listDataReducer from '../reducers/ListDataReducer'
const rootReducer = combineReducers({
listDataReducer, // Please add your reducer here
});
export default rootReducer;
I also faced the problem.
What I did was instead of:
combineReducers(productReducer, cartReducer)
I did:
combineReducers({ productReducer, cartReducer })
and it worked.
It expects a valid object for the store.

Map redux dispatch to redux-form

Sorry if this has been answered elsewhere, I'm a Redux beginner, and I couldn't find anything related.
I'm having trouble mapping dispatch to ReduxForm. Im setting up my reducers like this:
import { reducer as formReducer } from 'redux-form';
import foo from './foo';
import bar from './bar';
const rootReducer = combineReducers({
foo,
bar,
form: formReducer
});
export default rootReducer;
and then combining them like so:
import rootReducer from '../reducers/index';
const loggerMiddleware = createLogger();
const createStoreWithMiddlware = applyMiddleware(
thunkMiddleware,
loggerMiddleware
)(createStore);
export default function configureStore(initialState) {
const store = createStoreWithMiddlware(rootReducer, initialState);
return store;
}
and then mapping dispatch to props like this:
function mapStateToProps(state) {
return {
foo: state.foo,
bar: state.bar
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(App)
And then I have a form component that I am wrapping in a reduxForm like this:
TestForm = reduxForm({
form: 'testForm',
fields: ['firstName', 'lastName', 'email']
})(TestForm);
export default TestForm;
But I get an error:
Warning: Failed propType: Required prop dispatch was not specified in ReduxForm(TestForm). Check the render method of TestFormParent.
What is the best way to inject dispatch into a form component?
Turns out the docs on npm are a little bit different, and more complete. If anyone else runs into this issue, use connectReduxForm instead of reduxForm solved the problem.
reduxForm works for version 4 of redux-form

Resources