생활코딩 react강의 6~7장

릿·2022년 3월 28일
0

생활코딩

목록 보기
4/4

Update

1) Create와 Update는 둘 다 화면의 변화가 일어나는 버튼이다. 그래서 return문에서 목록으로 묶자.

...
<ul>
	<li><a href="/create" onClick={event=>{
    	event.preventDefault();
        setMode('CREATE');
    }}>Create</a></li>
 	<li><a href="/update">Update</a></li>
</ul>
...

Updata라는 버튼은 상세페이지 들어갔을때만 보이고 보통 때는 안 보이는 게 세련된 방법일 것이다.

2) Update버튼을 잘라내고, 위쪽에 contextControl이라는 변수를 만들어서 초기값으로 null을 준다.
3) mode가 READ일 때만 나오게 하고 싶다. 그래서 작성해놓은 해당 if문에 contextControl에 위의 li태그문을 복사해넣는다.

let contextControl = null;
...
else if (mode === 'READ') {
	let title, body = null;
    for (let i=0; i<topics.length; i++) {
    	console.log(topics[i].id, id);
        if (topics[i].id === id) {
        	title = topics[i].title;
            body = topics[i].body;
        }
    }
    content = <Article title={title} body={body}></Article>
    contextControl = <li><a href="/update">Update</a></li>
}
...

4) contextControl을 return에 아까 li태그가 있던 곳에 중괄호를 하고 써준다.

...
<ul>
	<li><a href="/create" onClick={event=>{
    	event.preventDefault();
        setMode('CREATE');
    }}>Create</a></li>
 	{contextControl}
</ul>
...

이렇게 되면 상세페이지에 들어갔을 때만 Update가 나오게 된다.
5) Update했을 때 그 고유한 ID가 있을 것이다. 그 ID를 주소에 추가해주자.

...
    contextControl = <li><a href='/update/'+id>Update</a></li>
...

이렇게 하면 실제 url이 바뀌진 않지만 마우스를 올려보면 id값이 추가된 걸 확인할 수 있다.
6) Update버튼에 onClick이벤트를 추가하고, 함수식을 써준 다음 제일 먼저 event.preventDefault();를 써서 새로고침을 방지하고, setMode를 써서 mode를 UPDATE로 바꿔준다.

...
contextControl = <li><a href={'/update/'+id} onClick={event=>{
	event.preventDefault();
    setMode('UPDATE');
}}>Update</a></li>
...

7) if문에 mode가 UPDATE일 때 content에 Update컴포넌트가 나타나도록 조건식을 써준다.

// App.js

else if (mode === 'UPDATE') {
	content = <Update></Update>
}

8) Update컴포넌트를 작성하고, Create컴포넌트를 복사해온다. 매개변수로 props를 추가해주고 h2태그의 Create->Update, submit input의 value값을 Update로, onCreate를 onUpate로 변경한다.

function Update(props){
	return <article>
    	<h2>Update</h2>
        <form onSubmit={event=>{
        	event.preventDefault();
            const title = event.target.title.value;
            const body = event.target.body.value;
            props.onUpdate(title, body);
        }}>
        	<p><input type="text" name="title" placeholder="title"/></p>
            <p><textarea name="body" placeholder="body"></textarea></p>
            <p><input type="submit" value="Update"/></p>
        </form>
    </article>
}

그럼 이제 onUpdate prop을 전달해야 할 것이다.

9) 다시 if문으로 내려가서 Update태그에 onUpdate속성을 써주고, 함수식을 쓴 다음 매개변수로 title, body를 설정한다.

else if (mode === 'UPDATE') {
	content = <Update onUpdate={(title, body)=>{
    
    }}></Update>
}

Update는 수정이기 때문에 form에 기존의 내용이 담겨있을 필요가 있다. Update태그가 title값과 body값을 가지고 있어야할 것이다. 이전에 mode가 READ일 때 title값과 body값을 알아냈던 걸 떠올려보자.

10) mode가 READ일 때의 조건식에 있는 식을 복사해서 Update에 붙여넣어 준다. 그리고 Update태그의 title속성에 {title}, body속성에 {body}를 써주자.

else if (mode === 'UPDATE') {
	let title, body = null;
    for (let i=0; i<topics.length; i++){
    	if(topics[i].id === id){
        	title = topics[i].title;
            body = topics[i].body;
        }
    }
	content = <Update title={title} body={body} onUpdate={(title, body)=>{
    
    }}></Update>
}

11) 그리고 다시 Update컴포넌트로 올라가서 input태그에 value속성에 {props.title}, textarea속성에 {props.body}를 주면 화면의 input에 기존 내용이 나오는 걸 확인할 수 있다.

...
  <p><input type="text" name="title" placeholder="title" value={props.title}/></p>
  <p><textarea name="body" placeholder="body" value={props.body}></textarea></p>
  <p><input type="submit" value="Update"/></p>
...

그런데 input을 수정하려고 보니 수정이 안된다. props가 아닌 state를 써야 수정이 가능한 것이다.(props는 내용전달기능만 가지고 있다.)

12) Update컴포넌트에 props.title을 초기값으로 가지는 useState를 선언해주고, 매개변수로 title과 setTitle을 적어준다. 마찬가지로 body도 state로 선언해준다.

function Update(props){
	const [title, setTitle] = useState(props.title);
	const [body, setBody] = useState(props.body);
}

13) 그리고 input태그의 value속성도 props.title, props.body가 아닌 title, body로 바꿔준다.

  <p><input type="text" name="title" placeholder="title" value={title}/></p>
  <p><textarea name="body" placeholder="body" value={body}></textarea></p>
  <p><input type="submit" value="Update"/></p>

이렇게 해도 input의 값이 바뀌지 않는다.
14) onChange이벤트를 써보자. 함수 내에 setTitle값을 event.target.value로 지정해준다. textarea도 마찬가지.

  <p><input type="text" name="title" placeholder="title" value={title} onChange={event=>{
  	setTitle(event.target.value);
  }}/></p>
  <p><textarea name="body" placeholder="body" value={body} onChange={event=>{
  	setBody(event.target.value);
  }}></textarea></p>
  <p><input type="submit" value="Update"/></p>

input의 내용이 바뀔 때마다 onChange이벤트가 실행되면서, 그때마다 setTitle값이 바뀌면서 title값이 바뀌는 것이다. if문의 Update태그의 onUpdate함수에 console을 찍어보면 변경된 값이 잘 출력되는 걸 볼 수 있다. 그럼 실제 바뀐 값을 화면에 적용하려면 어떻게 해야할까?

15) if문의 Update태그의 onUpdate함수에 updatedTopic이라는 상수를 선언하고, id:id, title:title, body:body라는 객체를 할당한다.

16) 또 하나 바꿔야할 topics라는 state는 데이터가 배열이다. newTopics라는 상수에 [...topics]라는 값을 할당하여 topics를 복제했다.

17) 그리고 기존의 topics에서 id가 일치하는 걸 찾기 위해서 for문을 적어준다.

content = <Update title={title} body={body} onUpdate={(title, body)=>{
	const updatedTopic = {id:id, title:title, body:body}
    for (let i=0; i<newTopics.length; i++) {
    	if (newTopics[i].id === id) {
        	newTopics[i] = updateTopic;
            break;
        } 
    }
    setTopics(newTopics);
}}></Update>

Update란에 적은 대로 리스트 목록이 업데이트 되는 걸 확인할 수 있다. 그럼 다음 단계는 Update한 후에 상세보기 페이지로 넘어가게 만드는 것이다.

18) setTopics아래에 setMode('READ')를 쓰면 상세보기 페이지로 넘어가는 걸 확인할 수 있다.

Delete

Update버튼 밑에 Delete버튼을 만들 것이다. Create와 Update는 누르면 특정 링크로 이동하기 때문에 a태그로 만들어줬지만 Delete는 누르자마자 삭제시켜버릴 것이기 때문에 button태그로 만들어 줄 것이다.

1) if문의 mode가 READ일 때 contextControl내용이 써있는 구문으로 가서 기존에 있던 li태그에 추가로 li태그를 더 넣어줄 것이다. 하지만 리액트는 최상위 태그 하나만을 가져야하는 규칙이 있기 때문에 빈태그로 감싸주자. 그리고 newTopics라는 빈배열을 선언하고, for문을 돌려서 id값이 같지 않은 인덱스만 newTopics배열에 push하도록 적자. 그리고 삭제 후에는 mode를 welcome으로 바꿔준다.

contextControl = <>
	<li><a href={'/update'+id} onClick={event=>{
    	event.preventDefault();
        setMode('UPDATE');
    }}>Update</a></li>
    <li><input type="button" value="Delete" onClick={()=>{
    	const newTopics = [];
        for (let i=0; i<topics.length; i++) {
        	if (topics[i].id !== id) {
            	newTopics.push(topics[i]);
            }
        }
        setTopics(newTopics);
        setMode('WELCOME');
    }}
</>
profile
항상 재밌는 뭔가를 찾고 있는 프론트엔드 개발자

0개의 댓글