I have a react form with a textarea element that is essentially re-rendering or 'losing focus' after every character typed. I'm aware this question has been discussed on SO at length, but I'm wondering if my situation may differ given the form's placement within react-leaflet's Popup container. Many of the answers offered on SO for this situation suggest that the component is defined within a render function. I've seen one suggestion related to styled components that prompts me to raise this question. Am I implicitly re-rendering my form due to the use of the Popup container? Or am I possibly overlooking the use of my return function? Thank you for reading this far - I'd appreciate any thoughts you might have.
[EDIT] I've done further testing, and my form/textarea works as intended outside the Leaflet popup, and is isolated to the onchange action as expected.
In my application, the following is defined within my app() function:
const [commentValue, setCommentValue] = React.useState({
comment: ""
})
function handleCommentSubmit(e) {
e.preventDefault();
console.log('submitted comment');
console.log(commentValue);
}
function handleCommentValue(e) {
console.log('value is' + commentValue)
setCommentValue({
[e.target.name]: e.target.value
});
}
The broad app function returns my React.Fragment, which contains my leaflet map and the following popup with form:
{activePark && (
<Popup
position={[
activePark.ycoord,
activePark.xcoord
]}
onClose={() => {
setActivePark(null);
}}
>
<div>
<h2>{activePark.name}</h2>
<p>{activePark.description}</p>
</div>
<div>
<form onSubmit={handleCommentSubmit}>
<label>
Add Comment:
<textarea name="comment" onChange={handleCommentValue} value={commentValue.comment} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
</Popup>
)}
Including activePark related code below, as suggested by Mark:
//declared in my main app function
const [activePark, setActivePark] = React.useState(null);
/*Declared in the app function's return; park is just json that I've fetched from my flask api*/
<Marker
key={park.id}
position={[
park.ycoord,
park.xcoord
]}
eventHandlers={{click: () => {
setActivePark(park);
console.log('marker clicked')}, }}
icon={skater}
/>
If you pass a callback as shown below into setCommentValue(), this should work:
function handleCommentValue(e) {
console.log('value is' + commentValue)
setCommentValue(prevState => ({
...prevState,
[e.target.name]: e.target.value
}));
}