React Hooks - losing focus after typing one value - javascript

My form component inputs loses focus everytime I type and change the state, dunno why it loses focus.
This is a link to the sandbox with the same issue
https://codesandbox.io/s/quiet-dew-cf5wr?file=/src/App.js

Have you try to put const MotionStack = motion(Stack); outside of the Form function?
...
+ const MotionStack = motion(Stack);
function Form() {
- const MotionStack = motion(Stack);
...
}
I think that is messing with the lifecycle, because is getting re-generated every single time you update the state.
Another option is to use React.useMemo, to prevent MotionStack from being re-generated.
const MotionStack = React.useMemo(() => motion(Stack), []);

This already has been solved, my Motion div was inside the component resulting it on also rerendering everytime I type. I just moved it out the function.

Related

React useState doesn't update even with useEffect added

Probably it is a classic issue with useState which is not updating.
So there is a tree with some checkboxes, some of them are already checked as they map some data from an endpoint.
The user has the possibility to check/uncheck them. There is a "cancel" button that should reset them to the original form.
Here is the code:
const [originalValues, setOriginalValues] = useState<string[]>([]);
...
const handleCancel = () => {
const originalValues = myData || []; //myData is the original data stored in a const
setOriginalValues(() => [...myData]);
};
...
useEffect(() => {
setOriginalValues(originalValues);
}, [originalValues]);
However, it is not working, the tree is not updating as it should. Is it something wrong here?
Just do the following, no need for ()=> the state will update inside the hook if called, plus change the constant it will cause confusion inside your code and protentional name clash later on, with the current state variable name, and also make sure your data are there and you are not injection empty array !!!! which could be the case as well !.
// Make sure data are available
console.log(myData)
// Then change the state
setOriginalValues([...myData]);

React, how can I submit updates to Input box when clicking outside the component

I am looking for a solution in which a user can enter text into an input, and when they click anywhere outside of the component, it submits, saves the value.
In my case I have a top level component which dynamically generates Text Input components.It passes in the properties including an UpdateValue function.
In these functional components I am using the ability to add an event listener to the document, and then I detect if the click comes from outside the component in question. Having done a lot of research on stackoverflow, this seems to be the agreed upon method.
useEffect(() => {
document.addEventListener('mousedown', handleClick);
return () => {
document.removeEventListener('mousedown',handleClick);
}
},[])
const handleClick = (e) => {
if(node.current.contains(e.target))
{
return;
}
updateValue()
}
I have this working, in that the function gets called when I click outside the component, however, the function invoked on the parent component no longer seems to have access to the state..they appear all empty. I can only guess that because we are using a generic javascript function initially, the call doesn't have access to react stack.
So, my question is, how can I make this work where I want a nested functional component that has an input, and when a user clicks off component, it runs the updateValue function which can then use some internal state data to properly update this in the DB.
FYI, I have a onchange() on the input, which updates the value in the parent component already.
So, UpdateValue() is a trigger to basically submit final changes to DB.
Your updateValue should be a callback that you create inside your functional component. That should take dependencies on the state that you define there. Use React.useCallback

React Hooks: Adding new fields to an Object state does not get reflected immediately

I am using React Hooks to manage states within a component.
const addNode = () => {
let pform = pForm
let handles = [vForm, yForm, hForm]
let access_info = [virtualForm, management1Form, management2Form, consoleForm]
let newObj = {
...currentForm,
p: pform,
handles: handles,
access_info: access_info,
}
console.log('newObj', newObj)
setCurrentForm(
newRouterObj
)
console.log(currentForm)
let currArr = [...addedNodes]
currArr.push(currentForm)
setAddedNodes(currArr)
intializeForms()
}
The function above is an onClick that I use when I press an Add button. The forms (pForm, vForm, yForm, etc.) are all separate states. I gather them together and put them into a single object newObj and use setCurrentForm to update the currentForm state to newObj.
When I console.log the newObj, everything goes in fine. However, when I check the currentForm after the setCurrentForm, the fields (p, handles, and access_info) are empty.
I know that states in React can have a delay in updates so I might have to use useEffect. However, in my use case, which is to gather different states and put them in as a new field in the currentForm state seems useEffect is not the best way to solve it. Can anyone help please?
You are misunderstanding exactly how useState works. When you call the useState setter function, the state value isn't actually updated immediately, instead it will trigger the component to re-render with the updated value. Even though you call the setter half way through the function, the state value will remain the original value for the entire lifetime of that function call.
You could slightly tweak what you have to be
const addNode = () => {
...
let currArr = [...addedNodes]
// you know that currentForm is supposed to be newObj, so just push that
// see my explanation above to understand why it currentForm isn't what you expect
currArr.push(newObj)
...
}
It's an async action so values will not be assigned/updated instantly. You need to watch for the changes using useEffect hook to log new values and to do anything in case
useEffect(() => {
// Whenever `currentForm` will be updated, this callback will be invoked
console.log('updated currentForm values', currentForm);
},[currentForm]);

Saving count variable when closing Dialog in React

I am using useState inside Dialog in React Material UI.
and I use useCallBack Function like this.
const [count,setCount] = React.useState({
count: 0
})
const countCallback = useCallback(
() =>
setCount({
...count,
count : count.count + 1
}),[setCount,count])
It shows incremented number when I click increment Button to execute this Callback in ChildComponent.
But when I closing Dialog and open Dialog again, count reset to 0.
Is there any way I can memorize count inside dialog?
I don't want to use Redux.
You can use localstorage for it and use it to get the initial value of count at component mounting using useEffect.
useEffect(() => {
const initialCount = localstorage.getItem("count"); //given that u name the localstorage variable as count when setting item //
if(initialCount){
setCount({count: initialCount})
}
},[])
You can use another useEffect to set the value of count or you can do it just before setting the state.
If you want to persist the code you have used you can set the state in parent component, send that state as a props to child component and return the new value from the child component back to parent component.
Following link will help you to pass data from child to parent component in react:
https://stackoverflow.com/a/44467773/8057264
Using this approach you can maintain the lastest count in your application.
Issue is, when you close the dialog, Dialog component unmounts due to which on opening the component again value of count sets to 0.
What you can do is, Send the value to parent component everytime it is changed. In parent component store the value in state/local storage and pass the value as a prop to dialog component.

Trigger event whenever validity changes in redux form

In my React + Redux + Redux-Form app, I need to enable/disable a "Next" button depending on the validity state of the form. This button is controlled by the parent component, so I can't just have <Button disabled={!props.valid}/>. Ideally redux-form would give me an event like onValidityChanged that I could listen for, and call the setCompleted() function passed down by the parent component whenever this happens. However such an event doesn't seem to exist. I also can't use the onChange hook, because at this point it won't have access to the props passed by the parent.
e.g.
function Parent(props){
const [completed, setCompleted] = React.useState(false);
return (
<div>
<Child setCompleted=setCompleted/>
<button disabled={!completed}>Next</button>
</div>
);
}
const Child = reduxForm({form: 'form'})(props => {
const {setCompleted} = props;
// Call setCompleted once this form becomes valid
});
How can I run an event whenever the validity of the form changes, but still have access to props?
One simple way of doing so would be to read the current validity status as Redux-Form updates it in your redux state, using a selector. You can even use one provided by the redux-form package: isValid. Since you're using hooks, you can also use react-redux's useSelector hook (if you're using react-redux v7.1.0 or higher).
The result would be:
import { useSelector } from 'react-redux`;
import { reduxForm, isValid } from 'redux-form`;
const Child = reduxForm({form: 'form'})(props => {
const { setCompleted } = props;
const isFormValid = useSelector(state => isValid('form')(state));
// Call setCompleted once this form becomes valid
if (isFormValid) {
setCompleted(true);
}
});
Of course you may want to extract this selector in another file and memoize it.
You may also want to use this hook (or its mapStateToProps equivalent) directly inside the parent component to avoid using the useState hook in the first place.

Categories

Resources