I have the following component:
import React, { useState } from "react";
import { FormControl, TextField } from "@material-ui/core";
interface IProps {
text?: string;
id: number;
onValueChange: (text: string, id: number) => void;
placeholder: string;
}
export const QuestionTextRow: React.FC<IProps> = (props) => {
const [item, onItemChange] = useState(props.text);
const onChange = (e: React.FormEvent<HTMLInputElement>) => {
const newValue = e.currentTarget.value;
onItemChange(newValue);
props.onValueChange(newValue, props.id);
};
return (
<>
<FormControl fullWidth>
<div>{props.text}</div>
<TextField
aria-label="question-text-row"
onDragStart={(e) => {
e.preventDefault();
e.stopPropagation();
}}
value={item}
onChange={(ev: React.ChangeEvent<HTMLInputElement>): void => {
onChange(ev);
}}
/>
</FormControl>
</>
);
};
It is rendered via the following component:
const renderQuestionOptions = (id: number): JSX.Element => {
const item = props.bases.find((x) => x.sortableId === id);
if (!item) return <> </>;
return (
<div className={classes.questionPremiseRow}>
<div className={classes.rowOutline}>
<QuestionOptionsSortableRow item={item} isDisabled={false} onClickRow={onClickBasisRow}>
<QuestionTextRow
text={item.text ? item.text.text : ""}
id={item.sortableId}
onValueChange={basisValueChanged}
placeholder={intl.formatMessage({ id: "question.create.basis.row.placeholder" })}
></QuestionTextRow>
</QuestionOptionsSortableRow>
</div>
</div>
);
};
It renders the following list:
As you can see props.text
and useState
item
from props.text
are rendered equally. If props.text
is updated it does not reflect on useState
though.
https://stackoverflow.com/a/53846698/3850405
I can solve it by useEffect
to make it work:
useEffect(() => {
onItemChange(props.text);
}, [props.text]);
https://reactjs.org/docs/hooks-effect.html
https://stackoverflow.com/a/54866051/3850405
However If I add key={`${item.text?.text}-${item.sortableId}`}
to QuestionTextRow
it will work without using useEffect
. How come?
I know a static unique key should be used but would it not be the same result if key={item.uniqueId}
was used?
https://www.npmjs.com/package/react-key-index
The argument passed to useState is the initial state much like setting state in constructor for a class component and isn't used to update the state on re-render