Jeff
Jeff

Reputation: 21

Cannot Update State with Form onSubmit React

I have a component with a list of components. I have an initial cardlist which gets populated as the list in my component. Each time I submit the form I want to add a new component, but I can't get it to update even though my cardlist array gets a new card. What do I do?

import { Card } from "./Card";

export function Body() {
    let imgname = "";
    let imgurl = "";

    let cardlist = [
        {
            name: "ca122t1",
            url: "https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/other/cat_relaxing_on_patio_other/1800x1200_cat_relaxing_on_patio_other.jpg"
        },
        {
            name: "cat2",
            url: "https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/other/cat_relaxing_on_patio_other/1800x1200_cat_relaxing_on_patio_other.jpg"
        }
    ]
    const [list, setList] = React.useState(cardlist);
    
    
    function handleName(event) {
        imgname = event.target.value;
    }

    function handleURL(event) {
        imgurl = event.target.value;
    }

    function handleSubmit(e) {
        let imgToAdd = {name: imgname, url: imgurl}
        cardlist.push(imgToAdd)
        setList(cardlist)
        e.preventDefault()
    }

    return (
        <div>
            <form onSubmit={handleSubmit}>
                <label>Name</label>
                <input type="text" onChange={handleName}/>
                <label>Image URL</label>
                <input type="text" onChange={handleURL}/>
                <input type="submit" value="Submit"/>
            </form>
            <ul>
                {list.map((item) => (
                    <Card name={item.name} url={item.url}></Card>
                ))}
            </ul>
        </div>
    );
}

Upvotes: 0

Views: 563

Answers (1)

Taxel
Taxel

Reputation: 4207

Never modify state in React directly. Instead, copy the values of the old array into a new one. Also, you should use the old state (list) and not your cardlist variable which is just used for initializing the state. In ES6 you can simply do

function handleSubmit(e) {
  // copy the elements of list into a new array and add the new card
  setList([...list, {name: imgname, url: imgurl}]);
  e.preventDefault();
}

EDIT: I just saw that you are also not using state for the imgname and imgurl variable, so this answer should work but fill in empty strings for the new values. Everything that changes in a component should useState:

const [imgname, setImgname] = useState("");
function handleName(event){
  setImgname(event.target.value)
}

Also, for controlled inputs, set the value from state to avoid inconsistencies:

<input type="text" onChange={handleName} value={imgname} />

Upvotes: 1

Related Questions