DLateef
DLateef

Reputation: 251

useState not forcing re-render of react component

I have a component which a prop value which is an object, one of the properties of value is aliases which is an array of string. I have an add alias button which should add an alias to the object. I am displaying all aliases with .map in the component, but when I add an alias the component does not re-render. I can see the state updating properly with react dev-tools in the browser, but the component does not re-render the updated list. What am I doing wrong?

import Accordion from "@components/common/Accordion"
import Alias from "./value-form/Alias"

const ValueItem = props => {
    const { value } = props
     
    /** EXAMPLE VALUE 

                   "id": 1,
                "name": "Primary Descriptor",
                "programmaticName": "Primary_Descriptor",
                "fileTypeDetailId": 9,
                "fileType": "File Type no. 9",
                "standardValue": "Outgoing",
                "isActive": true,
                "aliases": ["Alias 1", "Alias 2", "Alias 3"]
    */


    const dispatch = useDispatch()


    const [formValue, setFormValue] = useState(value)
    const [formAliases, setFormAliases ] = useState(value.aliases)

    const addAlias = () => {
        const updatedFormValue = formValue;
        updatedFormValue.aliases.push("");
        setFormValue(updatedFormValue)
        setFormAliases(updatedFormValue.aliases)
    }



    return (
        <Accordion
            key={value.id}
            title={value.name} />
            }
        >
            <div className={styles.valueFormContainer}>

                {formAliases.map((alias) => {
                    return ({alias})
                }
                )}
                <Button handleChange={() => { addAlias()}} buttonLabel="+ Add Alias" buttonTypes={["orange"]} />
            </div>
        </Accordion>)
}

export default ValueItem

Upvotes: 1

Views: 118

Answers (2)

Majid M.
Majid M.

Reputation: 4974

You can't push new item to the array for updating state. Your push will mutate the state directly and that could potentially lead to error prone code. If you would like to push item to array of states, you can make a shallow copy of the state with destructuring-assignment, push to it and finally update the state with the copied array :

  const addAlias = () => {
        const updatedFormValue = formValue;
        let copy = [...updatedFormValue.aliases];
        copy.push("");
        setFormValue(updatedFormValue);
        setFormAliases(copy);
    }

Upvotes: 1

yairmea
yairmea

Reputation: 260

Your problem is right here

 const addAlias = () => {
    const updatedFormValue = formValue;
    updatedFormValue.aliases.push("");
    setFormValue(updatedFormValue)
    setFormAliases(updatedFormValue.aliases)
}

you are mutating the exists state.

https://reactjs.org/docs/hooks-state.html

in your case i'd use

setFormValue(prevState=>[...prevState,aliases:[...prevState.aliases,""])

Upvotes: 1

Related Questions