I'm trying to dispatch a function from a component which has route 'localhost:8080/location/:id' but it seems to give an error, the same dispatch function is working in other component which doesn't have param id.
This is error i'm getting while dispatching that action.
Uncaught TypeError: (0 , _bandwidth2.default) is not a function
This is my dispatchToProps.
const mapDispatchToProps = (dispatch) => ({
addBandwidth: (bandwidth) => dispatch(addBandwidth(bandwidth))
});
export default connect(undefined, mapDispatchToProps)(UpgradeBandwidth);
This is my action.
export const addBandwidth = (bandwidth) => ({
type: 'ADD_BANDWIDTH',
bandwidth
});
Just to clarify, this function working in other component but not in one which has param id in its route. Please help. Thanks.
This is where i called.
handleSubmit = (e) => {
e.preventDefault();
console.log(this.state)
this.props.addBandwidth({
_id: uuid(),
leasedCircuitId: this.state.leasedCircuitId,
bandwidth: this.state.bandwidth,
bandwidthUnit: this.state.bandwidthUnit,
bandwidthType: this.state.bandwidthType,
lastMile: this.state.lastMile,
remarks: this.state.remarks,
discountPolicy: this.state.discountPolicy,
status: false
});
}
Check your App.js
Are you shure you imported addBandwidth()?
import { addBandwidth } from 'path to your action'
Related
I've a simple app built on redux-toolkit. I am dispatching createProduct actions which is working fine. I want to navigate to /products/ page form /products/new page after createProduct action. How can I use navigate (react-router-dom) to do this.
I tried this inside action but failes
[createProduct.fulfilled]: (state, { payload }) => {
toast.success('Product Created Successfully!');
const navigate = useNavigate()
navigate('/products')
return {
...state,
loading: false,
products: state.products ? [...state.products, payload.product] : [payload.product]
};
},
I also tried passing navigate to payload but I encountered this error :
You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store.
I am dispatching createProduct like this
const handleSubmit = async () => {
console.log('formik.values', formik.values);
dispatch(
createProduct({
...formik.values,
category: formik.values.category._id,
subCategory: formik.values.subCategory._id
})
)
};
Reducer functions are pure functions, you can't issue the navigation action from the reducer, but you can from the asynchronous action or in the calling component. React hooks are also only valid in React functions or custom hooks.
Asynchronous actions return a Promise. You can chain from the resolved Promise, or await it, and issue the imperative navigation.
const navigate = useNavigate();
Using Promise chain:
const handleSubmit = () => {
dispatch(createProduct({
...formik.values,
category: formik.values.category._id,
subCategory: formik.values.subCategory._id
}))
.then(() => {
navigate('/products');
});
};
or async/await:
const handleSubmit = async () => {
try {
await dispatch(createProduct({
...formik.values,
category: formik.values.category._id,
subCategory: formik.values.subCategory._id
}));
navigate('/products');
} catch(error) {
// handle any rejections/errors
}
};
Yow guys, React beginner here.
So basically, I am trying to fetch the updated state using React useContext hook.
The state is set inside a function call where the dispatch is placed, and the function call is bind to the button onClick event.
The function where the dispatch is called:
const fetchLocation = async (id: number) => {
const [, result] = await getLatestLocation()
dispatch({
type: "LOCATION_FETCHED",
payload: result
})
console.log(result) //this prints the latest/updated location even on button first click
}
Reducer:
case "LOCATION_FETCHED": {
return {
...state,
location: payload,
}
}
The function call in the component:
const {
fetchLocation,
location
} = React.useContext(locationContext)
const [fetchingLocation, setFetchingLocation] = useState(false)
const getLocation = (id: number) => {
fetchLocation(id)
.then(() => {
setFetchingLocation(true)
})
.finally(() => {
setFetchingLocation(false)
console.log(location) //this prints nothing or empty on the first button click
})
}
Button onClick function bind:
onClick={() => getLocation(143)}
I'm not sure what is happening, the first click will log nothing but on the second click, I got the updated location state.
As the comments say, the dispatch works asynchronously. So if you want to know the new value you should use the useEffect hook like this.
useEffect(() => {
console.log(location)
}, [location])
You can read more about here: https://reactjs.org/docs/hooks-effect.html
Here is an example of it.
My Code is:
const mapDispatchToProps = dispatch => ({
onChangeHandler: (name,value) =>
dispatch({ type: "REGISTRATION", key: name, value })
});
But I need something like this:
const mapDispatchToProps = dispatch => ({
onChangeHandler: (name,value) =>
dispatch({ type: "REGISTRATION", key: name, value }).then((nextProps)=>console.log(nextProps))
});
Please help us.
Redux data flow out of the box is synchronous, so it doesn't make sense to "then" a dispatch as it doesn't return anything. You can read more about that here:
https://redux.js.org/advanced/async-flow
I would recommend looking at redux-thunk which allows you to decide when to dispatch, whether it be sync or async, and will allow you to retrieve the updated state from the store. It does this by allowing you to dispatch a function instead of an action. The function provides you dispatch and getState.
Here is an example:
const onChangeHandler = (name, value) => (dispatch, getState) => {
// Dispatch event
dispatch({ type: "REGISTRATION", key: name, value });
// Get updated state
console.log("state :", getState());
};
export default connect(null, { onChangeHandler })(MyComponent);
If you are however looking at creating a side effect of the store updating from within your component, I would recommend to use the useEffect hook for this to respond to updates as a result of the redux store state updating your components props.
Here is an example:
const MyComponent = ({key, value}) => {
useEffect(() => {
console.log(`key or value updated: ${key} ${value}`);
}, [key, value]);
return (
<span>Current props are {key} and {value}</span>
)
};
const mapDispatchToProps=dispatch=>({
addToCartHandler:data=>dispatch(addToCart(data)),
removeToCartHandler:data=>dispatch(removeToCart(data))
})
Im using React, Redux and Firebase to Authenticate user.
I have added into my component lifecycle ComponentWillMount
dispatch(onAuthStateChanged()) to execute this listener.
and my actions with middleware thunk
export const onAuthStateChanged = () => dispatch => {
auth.onAuthStateChanged(
() => {
dispatch({ type: CURRENT_USER, currentUser: auth.currentUser });
},
error => {
//system error
}
);
};
Does anyone know how I would get around to removing this listener with componentWillUmount??
I'm trying to combine actions inside mapDispatchToProps. Trying to fetch data and after launch modal dialog. But I keep getting Cannot read property 'then' of undefined error.
Could somebody explain me, what am I doing wrong?
mapDispatchToProps:
const mapDispatchToProps = dispatch => ({
onClick: id => {
// console.log(fetchThing(id)) returns undefined
dispatch(fetchThing(id)).then(() => {
dispatch(showModal())
})
}
})
Redux action:
export const fetchThing = () => {
const request = axios.get(URL_API)
return dispatch => {
request.then(response => {
dispatch({ type: ACTION_FETCH, payload: response.data })
})
}
}
Why don't you use redux-thunk? With that you can write your action like that:
export const fetchThing = dispatch => axios.get(URL_API)
.then(response => dispatch({ type: ACTION_FETCH, payload: response.data }))
Redux thunk middleware will do all the stuff for you and you do not need to do that each time you need async actions within the mapDispatchToProps.
mapDispatchToProps should not have side effects. This should only do as the name suggests and hook up the actions to redux. This should be:
const mapDispatchToProps = {
fetchThing: yourAction.fetchThing,
showModal: yourAction.showModal,
};
export default connect(null, mapDispatchToProps)(YourComponent);
Then in your (probably) button:
<button type="button" onClick={this.handleClick} />
// this can be an asynchronous function, or you can just handle it in the action.
handleClick = async id => {
await this.props.fetchThing(id);
this.props.showModal();
};