React 6.4 - dispatch method inside async action function with createBrowserRouter - react-hooks

I've got this on my routes:
{
path: "/user/login",
element: <Login />,
action: loginAction,
},
So, I'm reaching the login action correctly when I submit the form in the login page.
The issue is, I'm trying to store some data using reducers but inside the loginAction is giving me an error when try to use the
async function action({ request }) {
const formData = await request.formData();
const dispatch = useDispatch(); <-- ERROR here
action as been imported as loginAction
import { action as loginAction } from "./pages/Login";
This is the error I'm getting:
Line 38:20: React Hook "useDispatch" is called in function "action" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use" react-hooks/rules-of-hooks
Of course, if I change the "action" to "Action" it doesnt giving me any error (after fixing the import) but it just doesnt work.
Any clue how to use useDispatch inside a action function from React 6.4?
Thanks!
Use reducers in action function.

React Hook "useDispatch" is called in function "action" that is neither a React function component nor a custom React Hook function
as the error says, you cannot call a hook like this, inside a simple function ! you should call useDispatch:
const dispatch = useDispatch();
inside your function component and make sure that it is called at the top level.

Related

Can't clear inputs when using Remix.js Form element

when submitting remix form with <Form>element i can't clear inputs after submit. In my particular case, that form is sitting on child route within <Outlet /> component (using nested routes here)
When form is submitted, all is working fine, redirect in handler goes to parent, parent is refreshing but child doesn't and inputs remains with values entered, that's a problem.
form is quite regular, inputs and button, all manages action function in parent
export const action: ActionFunction = async ({ request }) => {
const formData = await request.formData()
const data = Object.fromEntries(formData)
await doSomething(data)
return redirect('/route/add')
}
When instead of remix <Form/>element i use regular <form> element (its the only change) - total form refresh happen - and its also working, but extra request processing, and is impossible to use tasty remix hooks, like useTransition
how i cut the corner
const submit = useSubmit()
function submitHandler(evt) {
evt.preventDefault()
// total shame
evt.target.title.value = ''
evt.target.body.value = ''
submit(evt.target, {
action: '/route/add',
method: 'post',
})
}
so question is: how clear inputs after submitting ?
This is actually more of a React question instead of a Remix one.
Remix doesn't unmount your Outlet on navigation.
Remix is simply fetching data from your loaders and React is then rendering. As you know, initial state and default value do not get reset on re-render. The component must unmount. The simplest way is to update the key prop to trigger React to remount.

What's wrong with this React Custom Hook?

I've read numerous articles on creating and using Custom Hooks in React but can't figure out why my code is not working.
Here is the heart of the problem code:
cont MyContextProvider = (props) => {
const useCompleteWizard = () => {
// Define `body` object
useEffect(() => {
// const { loading, data } = useFetchPost(`${API_ROOT()}account_management/fleets`, body, app.awsConfig);
useFetchPost(`${API_ROOT()}user_management/users`, body, app.awsConfig);
}, []);
}
}
Within my context provider, I've created the custom hook you see, which in turn calls another custom hook that posts the data.
But I'm getting this error:
React Hook "useFetchPost" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.
I don't see that useFetchPost is being called inside a callback. Which callback? This just doesn't make any sense to me and I'm hoping someone can enlighten me.
Hey you are calling a custom hook inside useEffect callback.you know useEffect take
a callback function.please call your custom hook outside of this effect
please checkout this Invalid Hook Call Warning
https://reactjs.org/warnings/invalid-hook-call-warning.html

Global dialog implementation with vue

I am need a reusable, global dialog/modal component in my vue application. I need to be able to call it from any component and update its header text, body text and callback function once the dismiss button is pressed on the modal. I have tried importing a custom made dialog component into each component where I plan to use it and I have tried creating a global dialog where the values would be set using a mutable values in a modals vuex modal. This latter did not work because vuex will not store functions as values. I am new to vue and am not too sure how to go about this and absolutely any advice on a good way to go about it would help tremendously.
I did something like that before. The main ingredient is the handling of events through the $root because you can't relay in this scenario on the normal component communication.
// In your Global Modal
<script>
export default {
name: 'GlobalModal',
mounted () {
this.$root.$on('callGlobalModal', () => {
this.dialog = true
})
},
data: () => ({
dialog: false,
}),
}
</script>
Then call it frome anywhere using this.$root.$emit('callGlobalModal')

Redux-Form file upload after async validation

I have a FileUpload component that is connected through a redux-form Field. It calls input.onChange and input.onBlur with the selected file as a base64 string when a file is selected in an input field.
I'm using the asyncValidator redux-form option to validate the dimensions of the image, and I would like the file to be uploaded to the my server after the async validation has finished.
There doesn't seem to be any sort of afterAsyncValidation hook documented. What is the best way to accomplish this in redux-form?
redux-form was designed with the idea that your data would be saved to the server on submit.
However, there's nothing stopping you from putting your own .then() clause after your async validation to do that. Something like this?
// async function you already have that is looking at your
// picture field and rejecting the promise with errors
import validateDimensions from './validateDimensions'
// async function to upload the image
import upload from './uploadImage'
const MyForm = reduxForm({
form: 'myForm',
asyncValidate: values =>
validateDimensions()
.then(() => {
// we know validation passed
upload(values.prettyPicture)
// ^ not "return upload(values.prettyPicture)" to let this async
// validation promise resolve and do upload asynchronously
// after it has resolved
})
},
asyncBlurFields: [ 'prettyPicture' ]
})(MyForm)

React Native Event Emitter between components

I have two components in react native. One class name is firstClass, and the second class is secondClass. "secondClass" is a child view of firstClass. I can submit my data to my firebase from the child view, but on successful submit, I want the view to go back to "firstClass".
I have used event emitters in the past, but those were only using navigatorIOS.
My question is, does the event emitter system listen to global events, or just within their class? And if so, how do I communicate from "secondClass" to "firstClass", that I want to show "firstClass" again.
Thanks!
You can use a callback function and call it from the second component :
in the first component:
//Constructor
....
this.state ={
renderSecondComponent:false
}
....
...Your code
{
this.renderSecondComponent()
}
renderSecondComponent(){
if(this.state.renderSecondComponent){
return(
<SecondComponent callback={()=>{this.setState({renderSecondComponent:false})}}/>
)
}
}
In the second component
....Your code
// when you should go back to the first component
if(this.props.callback){
this.props.callback()
}

Resources