React.Js - Input Losing Focus When Rerendering

React Js input is losing focus when I try typing in it but only when onChange is added

Move useState to TableRowWithSave and use value instead of defaultValue

function ConditionalTableRow(props) {
let { item, index } = props;
if ( index === editModeIndex)
return (<TableRowWithSave item={item} index={index} />)
else
return (<TableRowWithEdit item={item} index={index} />)
}

function TableRowWithSave(props) {
let { item } = props;
const [make, setMake] = useState(item.make);
return (
<TableRow>
<TableCell>
<input type="text" value={make} onChange={e => setMake(e.target.value)} />
</TableCell>
<TableCell>
<button className="palletSaveButton" onClick={handleSaveClick}> Save </button>
</TableCell>
</TableRow>
)
}

const AddMaker = () => {
return (
<TableBody>
{
records.map((item, index) => (
<ConditionalTableRow key={index} item={item} index={index} />
))
}
</TableBody>
);
}

EDIT: Also it's better to move ConditionalTableRow and TableRowWithSave outside AddMaker

React input text losing focus on rerender

I found it. Everytime I called ReactDOM.render I was redeclaring my top-level component function, which seems to cause my input text to lose focus. It must do an identity check on the passed component function/class to see if it's the same as the previous one and completely rerender from scratch if it's not.

So, here's how NOT to do it:

const render = props => {
const App = props => (
<Router history={browserHistory}>
<Switch>
<Route key="/login" path="/login" render={() => View(props)}/>
</Switch>
</Router>
);
ReactDOM.render(
<App {...props}/>,
rootDiv
);
}

render();
render();

Failing jsfiddle here: https://jsfiddle.net/chwsmchd/

Here's the correct way to do it:

const App = props => (
<Router history={browserHistory}>
<Switch>
<Route key="/login" path="/login" render={() => View(props)}/>
</Switch>
</Router>
);

const render = props => {
ReactDOM.render(
<App {...props}/>,
rootDiv
);
}

render();
render();

Correct jsfiddle: https://jsfiddle.net/gzzpmpbz/

Which component needs keys to keep focus after rerender?

onChange = ({ value }) => {
if (this.props.onChange) {
// Check to see if the document value really has changed
if (value.document !== this.state.value.document) {
this.props.onChange(value); // <----- This line is ruining it for you
}
}
this.setState({ value });
};

The indicated line is ruining it for you, I didn't understand what you need it for.
If you want to trigger a callback when the state really changed you should do this via componentWillUpdate(object nextProps, object nextState) and there compare nextState.value.document with this.state.value.document like this:

componentWillUpdate = (object nextProps, object nextState) => {
if (nextState.value.document !== this.state.value.document)
this.props.onChange(nextState.value);
}

...or you could use the setState callback to trigger code after the state has updated:

onChange = ({ value }) => {
var newDocValue = value.document;
var oldDocValue = this.state.value.document;
this.setState({ value }, () => {
if (oldDocValue !== newDocValue)
this.props.onChange(newDocValue);
});
}

I personally would rewrite the whole component as a function component, as I consider the lifecycle- and change-reaction handling much easier with useEffect hooks.

Input loses focus after typing character React

You need to move the TestExperience out of FormTest.

import React from "react";
import { useState } from "react";

const TestExperience = (props) => {
const [name, setName] = useState("");

return (
<div>
<h1>Test Experience {props.num}</h1>
<input
type="text"
name="name"
placeholder="Name"
onChange={(event) => {
event.preventDefault();
setName(event.target.value);
}}
value={name}
/>
</div>
);
};

const FormTest = () => {
const processFormData = (event) => {
event.preventDefault();
console.log(event.target);
};
const [nums, setNums] = useState([1, 2, 3]);
const arr = nums.map((num, index) => (
<TestExperience num={num} key={index} />
));

return (
<div>
<form
onSubmit={(event) => {
processFormData(event);
}}
>
{arr}
//another way I tried to do it below //
{nums.map((num, index) => (
<TestExperience num={num} key={index} />
))}
<button
onClick={() => {
setNums([...nums, nums.length + 1]);
}}
>
Add one!
</button>
</form>
</div>
);
};

export default FormTest;

Code sandbox => https://codesandbox.io/s/trusting-elbakyan-mxrez?file=/src/App.js



Related Topics



Leave a reply



Submit