What's wrong with this React Custom Hook? - react-hooks

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

Related

React 6.4 - dispatch method inside async action function with createBrowserRouter

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.

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

How to reset wizard style redux form?

I am using the example http://redux-form.com/6.0.5/examples/wizard/ to accomplish my own form.
But how can I reset the first and second form when I use the wizard style form?
You can clear your form by calling dispatch(reset('myForm')); after you have submitted the data ideally at the parent component.
You can read more about it here
https://redux-form.com/6.7.0/docs/faq/howtoclear.md/
The tricky part is to make sure that dispatch is available at the component where you are submit (aka the parent component).
One way to do that is to wrap your parent component with connect(). After that, your component will receive a dispatch function as a prop. You can then use
this.props.dispatch.
This works for me
submitForm(values) {
const { dispatch } = this.props
axios.post(`YOUR_URL_HERE`, values)
.then(response => {
console.log(response.data)
dispatch(reset('MY_FORM'));
})
.catch(error => {
console.log("Unexpected error", error);
});
}

How to Include events (not event-plugin) in Ractive initialization/defaults?

I've read through the Ractive Documentation and I'm scratching my head a bit, because it seems like the default events initialization option allows me to do something - create new eventtypes - far more complex than what i need but conversely, there's no hook for the simpler, (more common?) task of defining default events
Could someone advise on how to provide global events that could be fired for traditional DOM events?
Example:
I have a 3 Component application page. I want to define a getOptions event, such that any <select on-click='getOptions'>...</select> will be handled by the same function. I don't want to have to define that function in each component.
My intuition would have been to do the following:
Ractive.events['getOptions'] = function(event){
//logic for getting the options for the value in event.keypath
}
or, if i wanted a true default that could be overridden...
Ractive.default.events['getOptions'] = function(event){
//logic for getting the options for the value in event.keypath
}
but my understanding of the documentation, is that Ractive.events and Ractive.default.events do not provide this, but rather provide a way to define new event plugins, that depend on a separate mechanism for getting fired:
Ractive.events.getoptions = function(node,fire){
//here goes logic for interacting with DOM event listeners, etc
}
//and then i would need to do this
ractive = Ractive.extend({...});
ractive.on('someOtherEventName',function(event){
//logic for getting the options for the value in event.keypath
});
//and then I could do this...
<select on-getoptions='someOtherEventName'>...</select>
but what would fire the getoptions in this case - from the template, rather than js ractive.fire()?
Would something like <select on-getoptions='someOtherFunction' on-click=getoptions>...</select> work? That seems very strange to me. Do I understand the concept correction? If not, what am i missing?
Is there a simple way to achieve the first example?
Ractive.events refers to custom events for mediating between the dom and the template:
Ractive.events.banana = function( node, fire ) { ... };
<div on-banana="doSomething()"/>
The handler for the event can either be the name of an event to fire, or a method on the component instance.
In your case, I think defining a method on the Ractive.prototype would be the best way to have a common handler:
Ractive.prototype.getOptions = function( /* pass in arguments */ ){
// and/or this.event will give you access
// to current event and thus context
// you can also override this method in components and
// call this base method using this._super(..)
}
// now any ractive instance can use:
<select on-click="getOptions(data)">...</select>
An event based approach usually entails letting the root instance or common parent in the view hierarchy handle same event across child components:
var app = new Ractive({
template: "<componentA/><componentB/>",
oninit(){
this.on( '*.getOptions', ( event, arg ) => {
// any child component (at any depth)
// that fires a "getOptions" event will
// end up here
});
}
});
// in component A or B:
<select on-click="getOptions">...</select>
UPDATE: If you wanted to assign an event handler to the prototype, so in essence every component is pre-wired to handle an event of a set name, you could do:
Ractive.prototype.oninit = function(){
this.on( 'getOptions', ( event ) => {
// handle any "getOptions" event that happens in the instance
});
}
Just be aware that you must call this._super(); in any component in which you also implement oninit:
var Component = Ractive.extend({
oninit() {
// make sure we call the base or event listener won't happen!
this._super();
// do this component instances init work...
}
}

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