React Redux CreateSlice Post Api is not taking the updated values - reactjs

I have an enpoint that takes formData and API gets POST method only. When the page renders it takes the initial values but I have another form to change the parameters, once I change the params it does not send the updated values.
PS. Using Redux Create Slice here is my code;
Form Page
parametersChange = form => {
... };
formatData = data => {
return form;
};
And my createSlice Method;
export const functionName = (data = {}) => (dispatch, getState) => {
........
}));
};
this.props.getLossAvoidanceList({...data }); };
This should update my createSlice Method, however, the datain my createSlice method is always returns undefined. Where am I doing wrong ?
const mapStateToProps = (state) => ({
.....
});
const mapDispatchToProps = {
...
};
export default connect(
....
)(withRouter(LossAvoidance));

I show your code and nothing found any wrong but I think the problem is in declaration of HOC
try that way
import { compose } from "redux";
export default compose(
withRouter,
connect(mapStateToProps, mapDispatchToProps)
)(LossAvoidance);

Related

TypeError: state.getIn is not a function

I'm implementing immutable on my react project, using it with redux, making state an immutable object using fromJS() function (from immutable library). In my reducer file, everything works, I receive an action, I can set the new value using setIn() function, and I can use getIn() function to access state.
But when I get state from connect() function, using mapStateToProps, even if console.log shows an apparently immutable object, I can't use immutable functions, like toJs() or getIn() here. I receive always this error: TypeError: state.getIn is not a function.
My index.js file
import React from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';
import PropTypes from 'prop-types';
import Button from '#material-ui/core/Button';
import { template as templateAction } from './actions';
import withReducer from '../../../reducer/withReducer';
import templateReducer from './reducer';
export const Template = ({ name, template }) => (
<Button onClick={template}>
{name}
</Button>
);
Template.propTypes = {
name: PropTypes.string.isRequired,
template: PropTypes.func.isRequired,
};
export const mapStateToProps = (state) => {
console.log('state is equal to', state);
return (
{
name: state.getIn(['templateReducer', 'name']),
});
};
export const mapDispatchToProps = (dispatch) => ({
template: () => dispatch(templateAction()),
});
export default compose(
withReducer('templateReducer', templateReducer),
connect(mapStateToProps, mapDispatchToProps),
)(Template);
Result of console.log(state)
Result of console.log(state)
PS: When I don't use immutable state, everything works well.
Looks like state inside mapStateToProps function is an object with one property of 'templateReducer' that has a value of type Map.
I'm a bit rusty with my React knowledge, but maybe sharing the code for templateReducer would be helpful.
What does withReducer('templateReducer', templateReducer) do with the reducer function?
Seems like it is setting the state from the reducer to the key templateReducer before sending it to the mapStateToProps function. (maybe??)
Probably, changing this function to access the State before using immutable methods will remove the error.
export const mapStateToProps = (state) => {
console.log('state is equal to', state);
return (
{
name: state['templateReducer']?.getIn(['name']),
});
};
Use connect from griddle-react not react-redux.

What does this syntax mean export default connect(mapStatetoProps, mapDispatchToProps)(LandingComponent)

A module I have contains the following line. connect seems to have two pairs of parentheses. What does this mean?
export default connect(mapStatetoProps, mapDispatchToProps).
(LandingComponent)
Tried to lookup various documentation
import { connect } from 'react-redux'
import { LandingComponent } from './Landing'
const mapStatetoProps = state => {
return {}
}
const mapDispatchToProps = dispatch => {
return {}
}
export default connect(mapStatetoProps, mapDispatchToProps)
(LandingComponent)
Expect to understand what the syntax means.
The second set of parentheses is because connect(..., ...) returns a function. This function is a component decorator which is why it is called with the landing component class.
If you split it up it might become clearer:
const decorate = connect(mapStatetoProps, mapDispatchToProps);
const ReduxConnectedLandingComponent = decorate(LandingComponent);
export default ReduxConnectedLandingComponent;
In this case decorate is a function that accepts a single component and returns a component. i.e. it takes the plain component and returns a smarter one which pulls props from the nearest provided store in the hierarchy.
Example:
const TodoItem = ({ todo, destroyTodo }) => {
return (
<div>
{todo.text}
<span onClick={destroyTodo}> x </span>
</div>
)
}
const mapStateToProps = state => {
return {
todo: state.todos[0]
}
}
const mapDispatchToProps = dispatch => {
return {
destroyTodo: () =>
dispatch({
type: 'DESTROY_TODO'
})
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoItem)
mapStateToProps and mapDispatchToProps are both pure functions that are provided the stores “state” and “dispatch” respectively. Furthermore, both functions have to return an object, whose keys will then be passed on as the props of the component they are connected to.
In this case, mapStateToProps returns an object with only one key : “todo”, and mapDispatchToProps returns an object with the destroyTodo key.
The connected component (which is exported) provides todo and destroyTodo as props to TodoItem.
Source: https://www.sohamkamani.com/blog/2017/03/31/react-redux-connect-explained/

Actions must be plain object. Use custom middleware

I am using Redux,redux-thunk with react. I am returning an object but still getting the error.
authActions.js
export function register(){
return (dispatch)=>{
console.log("in register action");
dispatch({type:'auth_user'})
}
}
calling this action from Register.js using connect and props
import * as actions from '../actions/authActions';
class RegisterForm extends React.Component{
handleRegister = (e)=>{
e.preventDefault();
console.log("inside handle register");
console.log(this.props);
this.props.register();
}
}
var Register = connect(mapStateToProps,actions)(RegisterForm);
Error is
Actions must be plain objects. Use custom middleware for async actions.
EDIT 1
Implemented redux-thunk like below.
import thunk from 'redux-thunk';
const store = createStore(authReducer,applyMiddleware(
thunk,
loggerMiddleware
),window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'));
The code can be found on github using link
https://github.com/abhikulshrestha22/social-network/tree/master/client
You're using register from mapDispatchToProps:
this.props.register();
But it's just:
var Register = connect(mapStateToProps,actions)(RegisterForm);
So, calling register wouldn't work because it's in actions, actions.register:
var Register = connect(mapStateToProps,{register: actions.register})(RegisterForm);
Now, it should fix your issue.
actions/index.js
// with thunk
export const register = () => dispatch => (
dispatch({ type: 'auth_user' })
)
// without thunk
export const register = () => ({ type: 'auth_user' })
component/example.js
import React from 'react';
import { connect } from 'react-redux';
import { register } from '../actions';
const Example = ({ register }) => (
<button onClick={register}>Register</button>
)
export default connect(null, { register })(Example);
reducers/index.js
const authReducer = (state=false, {type, payload}) => {
switch(type) {
case 'auth_user': return !state;
default: return state;
}
}
There is nothing wrong with the current setup that you showed above.
I think your mapDispatchToProps may be the root cause of this problem.
You should declare your connect likes this
export default connect(
null,
{ register }
)(Register);
instead of (if I'm not wrong)
const mapDispatchToProps = dispatch => {
return {
register: () => {
dispatch(register());
}
};
};
export default connect(
null,
mapDispatchToProps
)(Register);
That's my guess. Hope this may help you.
handleRegister = (e) => {
...
this.props.dispatch(register());
}
Of course:
Apply redux-thunk middleware
In Register.js import register() action
Connect Register component to Redux store with react-redux connect()
EDIT:
If this simplified code (without mapDispatchToProps) doesn't work, something is wrong with your question.
Maybe your action payload contains something that's not a plain object? E.g. promise returned by axios?
Code Sandbox according to your question, everything seems to work fine:
https://codesandbox.io/s/j2mny6rvnv

this.props... is not a function react react-redux

I have a problem with dispatching a action from componentDidMount...
error is : TypeError: this.props.postDetails is not a function
Action.js
export const postDetails = data => ({
type: "POST_DETAILS",
post: data
})
Container/GetDetails.js
import Details from '../components/Details'
import { postDetails } from '../actions'
const mapStateToProps = state => ({ post: state.post });
const mapDispatchToProps = dispatch => bindActionCreators({postDetails}, dispatch);
const GetDetails = connect(
mapStateToProps,
mapDispatchToProps
)(Details)
export default GetDetails
Component/Details.js
import React from 'react'
import { postDetails } from '../actions'
class Details extends React.Component {
constructor(props){
super(props);
}
componentDidMount() {
console.log("did mount details");
this.props.postDetails();
}
render() {
return (
<div>
Details page
</div>
)
}
}
export default Details;
Can someone help me? Why i have this error?
In App.js (or wherever you are importing the Details component), are you using the path to your GetDetails container (not component)?
I moved state from a component to a container and forgot to update the import path which gave me this same error. Updating the import path to the container took care of it.
Edit:
For example, I have an apiLanding folder that has apiLanding.js (the component) and apiLanding-container.js (the container).
In my app.js, I needed to change
import apiLanding from './components/apiLanding/apiLanding';
to
import apiLanding from './components/apiLanding/apiLanding-container';
That way, the app now has access to the redux state and actions. This was a silly mistake and may not be your issue, but wanted to share just in case the import path was overlooked.
You have to return an object, where the keys are your props. See docs.
const mapDispatchToProps = dispatch => ({ postDetails: bindActionCreators({postDetails}, dispatch) })
Or, you can use the shorthand notation:
const GetDetails = connect(
mapStateToProps,
{ postDetails }
)(Details)
I don't see bindActionCreator imported. Use eslint to get rid of these errors
There are two things which don't really seem right to me. Personally I never used bindActionCreators. I would just create my mapDispatchToProps as following:
const mapDispatchToProps = dispatch => {
return {
postDetails: () => dispatch(actions.postDetails)
};
};
But also your postDetails call expects an argument, which you should add in your function call. So your mapDispatchToProps would look like this:
const mapDispatchToProps = dispatch => {
return {
postDetails: (data) => dispatch(actions.postDetails(data))
};
};
Also you're importing your action as postDetails. Are you sure that this is just one action? And not a combination of all actions in your file? Note how I added your function as actions.postDetails instead of just postDetails.

create-react-app (react redux) Multiple actions in connect

I am creating a React app with Create-React-App using Redux.
Following a tutorial, all the actions are put into 1 file:
src\action\index.js
export const fetchUser = (useCache = false) => async dispatch => { .. }
export const getUser = (useCache = false) => async dispatch => { .. }
export const fetchAlerts = (useCache = true) => async dispatch => { .. }
and then I connect them to my components using Connect:
import * as actions from "../../actions";
....
export default connect(mapStateToProps, actions)(Home);
However I would like to organize my actions into files, having a Accounts Action, and a Alerts action for this example. And I may want to call functions from each action in the 1 component.
My problem I'm having is I cant figure out how to add multiple actions into the 1 connect statment:
export default connect(mapStateToProps, actions)(Home);
The actions accepts an object or a function... Arrays dont work..
You're almost there, since you know mapDispatchToProp param of connect() can be object as well, you can always use
Object.assign({}, userAction, alertAction)
Or with object spread operator
{...userAction, ...alertAction}
To map all the actions to your Home component with redux you can do something like:
import * as actions from "../../actions";
const mapDispatchToProps = dispatch => {
return {
fetchUser: (useCache = false) => dispatch(fetchUser),
getUser: (useCache = false) => dispatch(getUser),
fetchAlerts: (useCache = true) => dispatch(fetchAlerts)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
See if this helps.

Resources