I have a member function for my react component. In that function I use set state to update component state using this.setState. Now I use the same function in all of my components. Can I make it as a common function? Then how can I access this for calling this.setState inside this common function
Related
I'm calling a component <B setHasChecked={()=>{setCheckedClientId(true)}}/> from within component "A", inside component "A" I declare the hook const [checkedClientId, setCheckedClientId] = useState(false);, and inside component "B" I execute props.setHasChecked();.
Even though this is working fine, i still get an error on the console:
React has detected a change in the order of Hooks called by "A"
Previous render Next render
------------------------------------------------------
1. useState useState
2. undefined useRef`
that's because you are not passing any parameter to props.setHasChecked();
I would suggest better pass a callback function from A to B. And in the callback function which resides in A you can call the setChecked function.
I have a few questions related to each other regarding React hooks: useState and useCallback.
When exactly is a functional update required?
1.1. If the setter function receives a function its argument will ALWAYS be the previous state?
If I want to update the parent state from the child component, how should I pass the setter to the child- wrap it in another function as a callback as explained here? just pass it directly as suggested here?
2.1. What are the reasons and advantages/disadvantages of each approach?
If I can just pass it directly and I am using memo, is useCallback required as explained here?
If I want to use the most recent state data when updating the parent state from the child, how should I do this?
4.1. Is passing a callback to the child useful in that case?
1. When exactly is a functional update required?
You may need to update any state on your component. For example, you are getting user from server via api and you need to store that user on your component. To do so, you need useState to store that user object. Here is the example:
const [user, setUser] = useState({}); // declaration
let newUser = u; // u is coming from api
setUser(newUser);
1.1. If the setter function receives a function its argument will ALWAYS be the previous state?
Yes. setter function like setState is used in class component. Here is the example of only update a state field:
this.setState({username: 'khabir'});
here you are updating state using previous state:
this.setState(prevState =>{
return{
counter : prevState.counter +1
}
})
2. If I want to update the parent state from the child component, how should I pass the setter to the child- wrap it in another function as a callback as explained here? just pass it directly as suggested here?
Both examples are same. you can use anyone.
3. If I can just pass it directly and I am using memo, is useCallback required as explained here?
If you pass any function reference to the child component from parent component, it is being created on every render of Parent and hence prevProps and props is not the same anymore even though they are.
To apply the memo, we need to make sure that function reference is not unnecessarily recreated on every render of Parent. That's why useCallback is used. Please read that article completely for better understanding.
4. If I want to use the most recent state data when updating the parent state from the child, how should I do this?
You can not update parent state directly from child component but you can send function reference to child component and call that function from child component that defined (the function) on parent component. In that function body (in parent), you can update your state of parent component.
4.1. Is passing a callback to the child useful in that case?
Yes as I said on the answer of question number 4.
I'm building a <BasicForm> component that will be used to build forms inside my application. It should handle submit, validation and also should keep track of the inputs state (like touched, dirty, etc).
Therefore, it needs some functions to do all that and I've been wondering what is the best place to put those declarations (concerning code organization and performance optimization, considering React and JavaScript best practices).
I'm using React 16.8 hooks and bundling with Webpack.
So far, here's what I've got:
BasicForm.js
/* I moved those validating functions to a different file
because I thought they are helpers and not directly related
to my BasicForm functionality */
import { validateText, validatePassword, validateEmail } from './Parts/ValidationHelpers';
function BasicForm(props) {
const [inputs, setInputs] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
// These are functions to handle these events
function onChange(event) {...}
function onBlur(event) {...}
function onFocus(event) {...}
// This function creates the initial state for each form input
function setInputInitialState(inputProps) {...}
// This functions does what it name says
function validateAllFields() {...}
// This one also
function checkValidationAndSubmit() {...}
return(
<FormContext.Provider value={{
onBlur: onBlur,
onFocus: onFocus,
onChange: onChange,
inputs: inputs,
setInputInitialState: setInputInitialState
}}>
<form onSubmit={onSubmit} method='POST' noValidate>
{props.children}
</form>
</FormContext.Provider>
);
}
My question is: as you can see, up to this point, I'm declaring all the functions that my <BasicForm> uses (onChange, onBlur, onFocus, setInputInitialState, validateAllFields, checkValidationAndSubmit) inside the body of my BasicForm React component function.
Is this the best practice? If I was using classes those functions would probably be methods of my BasicForm class. But since I changed to hooks and got rid of most classes, I always have doubts about placing auxiliar functions inside or outside my React components function's body. Is there a best practice for this?
When the auxiliar function may need some variables or state from my main function, I could always pass them as parameters when I call them (if they are declared outside).
Do I gain or lose anything if I declare them outside of my BasicForm function? Keeping in mind that this is a module that gets bundled with Webpack.
If the function does not rely on props or state, then it is best to define it outside of your component function. If it does rely on props or state, then it generally makes sense to define it inside your component function, but if you are passing the function as a prop to a child component, then you should consider using useCallback (though this generally only adds value if the child component is memoized).
When the function depends on props or state, if you move the function out of the component and pass it arguments, you will end up needing to wrap that call in another function (e.g. ()=>helperFunc(prop1, someState)) in order to pass it as a prop to a child component. If the function is large, you may still want to pull it out of the component in that manner, but that just comes down to style preferences.
For more information on useCallback, see my answer here: Trouble with simple example of React Hooks useCallback
Should react component state is meant to be used in the component in which it is defined?
I faced a scenario, where a component state is updated by two different components and is passed as a prop to its child. But never used in the component where it is defined.
For example: I have a component CommonComponent which has a state, 'stateObj' and it has two child components ChildComponent and ModifyComponent.
I have one more component, CreateComponent which is a parent of CommonComponent.
I have two cases here:
During create action, CommonComponent receives props from CreateComponent and updates the state- 'stateObj' and is passed as a prop to ChildComponent
During modify action, ModifyComponent updates the state of CommonComponent using a callback and in turn the 'stateObj'
is passed as a prop to ChildComponent
Is this a valid way of using the component's state? As I understood, The state is meant to be used by its component in which it is defined. But, here I am not using the 'stateObj' in CommonComponent. but, i am just using it to send data to its child components. Am I using the state in a right way? or is there any other way of doing this?
your suggestions are really precious!
Thanks in advance.
You could move the state to CreateComponent instead of having it in CommonComponent. So, ModifyComponent and CommonComponent will have callback props which will update the state in CreateComponent.
I had a case when I need to call a child function in my App.js component.
The short schema look like this :
Where I need to call the function() from the App.js, and the the function triggers something directly inside the Child 3 component.
I'm avoiding using function props drilling from the parent where this could be another problem in the future.
I tried to use Redux to dispatch the function into store, but Redux doesn't allow non-object properties to be stored.
Any help would be appreciated!