본문 바로가기
프론트엔드/React

리액트 배열에 데이터 수정하기

by 랼랼 2022. 5. 15.

하위 컴포넌트에서 상위 컴포넌트의 함수, 내용을 변경하려면 props를 이용한다.

 

배열 데이터를 수정하기 위해서는, 하위 컴포넌트에서 props로 변경할 state 객체와 setter를 받아 변경할 수 있습니다.

 

이번 실습에서는 동물들의 이름과 울음소리를 변경해보겠습니다.

 

0) 준비사항

 

animal 객체는 id, animalType, sound로 이루어져 있었습니다.

이 곳에 mode를 추가하여 수정 모드로 돌입하도록 표시하도록 하겠습니다.

 

App 컴포넌트

//animals state, 동물과 울음소리가 들어있음
const [animals, setAnimals] = useState([
    {
        id : 1,
        animalType : '고양이',
        sound : '야옹',
        mode : false
    },
    {
        id : 2,
        animalType : '강아지',
        sound : '멍멍',
        mode : false
    },
    {
        id : 3,
        animalType : '닭',
        sound : '꼬꼬댁',
        mode : false

    }
]);

 

App 컴포넌트는 state에 저장된 animals 객체와 AnimalList 컴포넌트를 이용하여 동물 울음소리를 표시해 줍니다.

다른 함수들과 CreateAnimal 컴포넌트에 관한 내용은 생략합니다.

 

App 컴포넌트

return(
    <div id="animalWrap">
        <div className="title">
            동물의 울음소리
        </div>
        <CreateAnimal
          animalType={animalType}
          sound={sound}
          onChange={onChange}
          onCreate={onCreate}
        />
        <AnimalList 
            animals={animals}
            onRemove={onRemove}
        }/>
    </div>
)

 

AnimalList 컴포넌트를 map을 이용하여 animals의 각 객체(animal)를 Aniaml 컴포넌트에 전달해 이를 출력합니다.

 

AnimalList 컴포넌트

function AnimalList({animals, onRemove}){
    return(
        <ul>
        {animals.map((animal)=>(
        <Animal
          key={animal.id}
          animal={animal}
          onRemove={onRemove}
        />)}
        </ul>
    )
}

 

Animal 컴포넌트에서는 animal의 내용을 표시합니다. 이 곳에 수정 모드로 전환할 수 있는 버튼을 만들어보겠습니다.

function Animal({animal,onRemove}){

    return(
        <li className="animal">
            <span>{animal.id} : </span>
            <b>{animal.animalType}</b>
            <span> {animal.sound}</span>
            <button className="update_button">수정</button>
            <button className="delete_button" onClick={()=>onRemove(animal.id)}>삭제</button>
        </li>
    );
}

 

지금까지의 결과입니다.

1) mode 변경

 

수정 버튼을 누르면 해당 animal 객체의 mode가 true로 변환되도록 하겠습니다.

App 컴포넌트에서 선언한 함수를 이용해 mode를 변환하는 방식을 사용하겠습니다.

 

App 컴포넌트에 toEditMode 함수를 선언합니다.

id를 인자로 받아, id가 일치하는 animal 객체의 mode를 true로 만들고,

그렇지 않은 객체는 mode를 false로 세팅합니다.

 

App 컴포넌트

//수정모드 전환
const toEditMode=(id)=>{
    //id 일치하지 않으면 mode false, 일치하면 mode true
    setAnimals(animals.map(animal=>animal.id===id?{...animal,mode:true}:{...animal,mode:false}));
}

 

이 함수를 이용하기 위해 AnimalList, Animal 컴포넌트까지 props로 전달해줍니다.

 

App 컴포넌트

return(
    <div id="animalWrap">
        <div className="title">
            동물의 울음소리
        </div>
        <CreateAnimal
          animalType={animalType}
          sound={sound}
          onChange={onChange}
          onCreate={onCreate}
        />
        <AnimalList 
            animals={animals}
            onRemove={onRemove}
            toEditMode={toEditMode}/>
    </div>
    )

 

AnimalList 컴포넌트

function AnimalList({animals, onRemove,toEditMode}){
    return(
        <ul>
            {animals.map((animal)=>(
                <Animal
                    key={animal.id}
                    animal={animal}
                    onRemove={onRemove}
                    toEditMode={toEditMode}
                />
            ))}
        </ul>
    )
}

 

Animal 컴포넌트에서는 수정 버튼을 누르면(onClick()) toEditMode()가 실행되도록 해줍니다. 이 때 인자는 id를 보내줘야 합니다.

 

Animal 컴포넌트

function Animal({animal,onRemove,toEditMode}){

    return(
        <li className="animal">
            <span>{animal.id} : </span>
            <b>{animal.animalType}</b>
            <span> {animal.sound}</span>
            <button
                className="update_button"
                onClick={()=>
                    toEditMode(animal.id)
                }>수정
            </button>
            <button className="delete_button" onClick={()=>onRemove(animal.id)}>삭제</button>
        </li>
    );
}

 

이제 수정 버튼을 클릭하면 해당 id를 가진 animal 객체는 mode가 true로 변환됩니다.

 

2) input 보여주기

 

이제 mode가 true라면 단어를 수정할 수 있도록 input을 보여주려고 합니다.

데이터 수정의 경우, 생성과 비슷한 과정을 거치겠지만, 차이점은 초기 input이 비어있는 것이 아니라

이전의 값이 채워져 있다는 점입니다.

input의 값을 채우기 위해 animal 객체를 받아 해당 내용을 채워놓도록 하겠습니다.

 

수정을 위한 input은 UpdateAnimal 컴포넌트를 새롭게 생성하여 사용하겠습니다.

내부의 input의 값을 채워야 하기에 animal을 props로 받아줍니다.

 

UpdateAnimal 컴포넌트

const UpdateAnimal = ({animal}) => {

    return (
        <div id="updateInputWrap">
            <div className="inline_box">
                <div className="input_box">
                    <input
                     name="animalType"
                     placeholder="동물 종류를 입력하세요"
                     defaultValue={animal.animalType}/>
                </div>
                <div className="input_box">
                    <input
                     name="sound"
                     placeholder="동물 울음소리를 입력하세요"
                     defaultValue={animal.sound}/>
                </div>
            </div>
            <div className="update_wrap inline_box">
                <button>수정</button>
            </div>
        </div>
    )
}

input의 초기값을 변경하려면 value가 아닌 defaultValue를 사용하여 변경합니다.

 

UpdateAnimal 컴포넌트는 수정 버튼을 눌렀을 때 보여집니다.

AnimalList 컴포넌트에서 삼항연산자를 사용하여 animal.mode가 true인 경우, UpdateAnimal 컴포넌트를 보여줍니다.

 

AnimalList 컴포넌트

function AnimalList({animals, onRemove,toEditMode}){
    return(
        <ul>
            {animals.map((animal)=>(
                animal.mode?
                <UpdateAnimal
                    key={animal.id}
                    animal={animal}
                />:
                <Animal
                    key={animal.id}
                    animal={animal}
                    onRemove={onRemove}
                    toEditMode={toEditMode}
                />
            ))}
        </ul>
    )
}

 

여기까지의 결과입니다.

수정 버튼을 누르면 Animal 컴포넌트가 아닌 UpdateAnimal 컴포넌트가 보입니다.

 

3) 수정한 내용 반영

이제 UpdateAnimal 컴포넌트에서 수정 버튼을 누르면 해당 데이터가 수정되도록 설정해보겠습니다.

이번엔 App 컴포넌트에서 state에 생성한 animals 객체와, setAnimals() 를 이용하겠습니다.

 

먼저, UpdateAnimal 컴포넌트까지 animal과 setAnimals를 props로 전달해줍니다.

 

App 컴포넌트

return(
    <div id="animalWrap">
        <div className="title">
            동물의 울음소리
        </div>
        <CreateAnimal
          animalType={animalType}
          sound={sound}
          onChange={onChange}
          onCreate={onCreate}
        />
        <AnimalList 
            animals={animals}
            onRemove={onRemove}
            toEditMode={toEditMode}
            setAnimals={setAnimals}/>
    </div>
)

 

AnimalList 컴포넌트

function AnimalList({animals, onRemove,toEditMode,setAnimals}){
    return(
        <ul>
            {animals.map((animal)=>(
                animal.mode?
                <UpdateAnimal
                    key={animal.id}
                    animal={animal}
                    animals={animals}
                    setAnimals={setAnimals} 
                />:
                <Animal
                    key={animal.id}
                    animal={animal}
                    onRemove={onRemove}
                    toEditMode={toEditMode}
                />
            ))}
        </ul>
    )
}

 

UpdateAnimal 컴포넌트에서는 전달된 animal 객체를 이용하여 새로운 state를 선언합니다.

이 state는 input의 내용이 바뀔때마다 변경되도록 할 것입니다.

 

UpdateAnimal 컴포넌트

const [updateAnimal, setUpdateAnimal]=useState(animal);

 

input의 내용이 변경될 때마다 state의 updateAnimal이 변경되도록 setUpdateAnimal을 이용합니다.

 

UpdateAnimal 컴포넌트

//수정 시 사용할 input state
const onChangeInUpdate=(e)=>{
  const {name,value}=e.target;
  setUpdateAnimal({
      ...updateAnimal,
      [name]:value
  });
};

 

수정 버튼을 클릭하면 map을 이용하여 animals의 데이터를 변경하는 함수를 생성합니다.

현재 수정한 데이터의 id와 일치하는 경우, updateAnimal의 mode를 false로 변경한 뒤 animals에 넣어줍니다.

 

UpdateAnimal 컴포넌트

const onClickForUpdate=()=>{
  // console.log(updateAnimal);
  setAnimals(animals.map(ani=>(
      ani.id===animal.id?{...updateAnimal,mode:false}:ani
  )));
}

 

input 요소에 onClick 이벤트와 onChange 이벤트를 연결시켜 줍니다.

 

UpdateAnimal 컴포넌트

return (
    <div id="updateInputWrap">
        <div className="inline_box">
            <div className="input_box">
                <input
                 onChange={onChangeInUpdate}
                 name="animalType"
                 placeholder="동물 종류를 입력하세요"
                 defaultValue={animal.animalType}/>
            </div>
            <div className="input_box">
                <input
                 onChange={onChangeInUpdate}
                 name="sound"
                 placeholder="동물 울음소리를 입력하세요"
                 defaultValue={animal.sound}/>
            </div>
        </div>
        <div className="update_wrap inline_box">
            <button onClick={onClickForUpdate}>수정</button>
        </div>
    </div>
)

 

최종 결과 작동하는 모습입니다.

 

동물 종류와 울음소리를 변경합니다.

 

반응형

댓글