변수 뿐만 아니라 함수명도 props로 전달 가능하다.
<Modal />
에 글제목, 글제목변경을 props로 전달해주었다.
{
modal === true ? <Modal 글제목={글제목} 글제목변경={글제목변경} /> : null
}
function Modal(props) {
return (
<div className="modal">
<h4>{props.글제목[0]}</h4>
<p>날짜</p>
<p>상세내용</p>
<button onClick={() => {
let copy = [...props.글제목];
copy[0] = '여자 코트 추천';
props.글제목변경(copy);
}}>글수정</button>
</div>
)
}
지금은 어떤 글을 누르든 첫 번째 글에 해당하는 모달창만 나온다.
각 글을 누르면 그 글에 해당하는 제목이 나오는 모달창으로 변경해보자.
0 -> 첫 번째 제목
1 -> 두 번째 제목
2 -> 세 번째 제목
글제목을 누르면! 그에 해당하는 제목이 모달창에 나와야 하므로 글제목의 onClick
에서 처리하면 된다.
let [title, setTitle] = useState(0);
...
{
글제목.map((item, i) => {
return (
<div className="list">
<h4 onClick={() => {
setModal(!modal);
setTitle(i);
}}>
{item}
<span onClick={() => {
let copy = [...따봉];
copy[i] += 1;
따봉변경(copy);
console.log(따봉);
}}>👍</span>
{따봉[i]}
</h4>
<p>2월 17일 발행</p>
</div>
)
})
}
...
function Modal(props) {
return (
<div className="modal">
<h4>{props.글제목[props.title]}</h4>
<p>날짜</p>
<p>상세내용</p>
<button onClick={() => {
let copy = [...props.글제목];
copy[0] = '여자 코트 추천';
props.글제목변경(copy);
}}>글수정</button>
</div>
)
}
title
, 글제목
, 글제목변경
은 App()
에 있으므로 props로 전달했다.
{
modal === true ? <Modal 글제목={글제목} 글제목변경={글제목변경} title={title} /> : null
}
🤔 근데 굳이
App
컴포넌트에 state를 만들어야 하나?
❌ 아니다.
Modal
컴포넌트에 바로 만들어도 된다. 그럼 부모(App
) -> 자식(Modal
)으로 전송할 필요가 없다.
그러나title
이라는 것이Modal
에서만 필요한 것이 아닌, 여러 컴포넌트에서 필요하다면 가장 상위 컴포넌트에 만들어야 한다. (만약,App
,Modal
에서 둘 다 필요하면App
에 만들어야 한다.)
state를 만드는 곳은 state를 사용하는 컴포넌트들 중 최상위 컴포넌트에 만들어야 한다!
<input>
에 글을 적고 버튼을 누르면 게시글로 추가되는 기능을 만들어보자.
<input>
에 뭔가를 입력했을 때 코드를 실행하고 싶으면 onChange
/onInput
를 사용할 수 있다.
<input>
에 입력한 값 가져오기
e
: 지금 발생하는 이벤트에 관련한 여러 기능이 담겨있다.
e.target
: 이벤트가 발생한 HTML 태그
e.target.value
: 이벤트가 발생한 HTML 태그에 입력한 값
<input type="text" onChange={(e) => {}} />
🤔 이벤트 버블링
근데 어제 모달창 만든 거 글제목 눌렀을 때만 모달창 나오는 게 아니라 좋아요 눌러도 모달창이 나오는데용...
👉 클릭 이벤트가 상위 HTML로 퍼진 것이다. 이벤트 버블링!
그럼 이걸 어떻게 막느냐? 👉e.stopPropagation();
<span onClick={(e) => { e.stopPropagation(); let copy = [...따봉]; copy[i] += 1; 따봉변경(copy); console.log(따봉); }}>👍</span>
🤔 state 변경함수는 늦게 처리 된다. 👉 비동기처리
글 발행/삭제 할때마다 배열을 새로 만들어서 setState로 처리하는데 이게 맞는 건지는 잘 모르겠다. 뭔가 별로인데... 좀 더 고민해봐야 할 것 같다.
function App () {
let [글제목, 글제목변경] = useState(['남자 코트 추천', '강남 우동맛집', '리액트독학']);
let [따봉, 따봉변경] = useState([0, 0, 0]);
let [modal, setModal] = useState(false);
let [title, setTitle] = useState(0);
let [write, setWrite] = useState('');
return (
<div className="App">
<div className="black-nav">
<h4>ReactBlog</h4>
</div>
<button onClick={() => {
let copy = [...글제목];
copy.sort();
글제목변경([...copy]);
}}>가나다순 정렬</button>
{
글제목.map((item, i) => {
return (
<div className="list">
<h4 onClick={() => {
setModal(!modal);
setTitle(i);
}}>
{item}
<span onClick={(e) => {
e.stopPropagation();
let copy = [...따봉];
copy[i] += 1;
따봉변경(copy);
console.log(따봉);
}}>👍</span>
{따봉[i]}
</h4>
<p>2월 17일 발행</p>
<button onClick={() => {
let temp = [...글제목];
temp.splice(i, 1);
글제목변경(temp);
let like = [...따봉];
like.splice(i, 1);
따봉변경(like);
}}>삭제</button>
</div>
)
})
}
{/* onChange에 input이 들어오면 그걸 알아내서 저장해두었다가 */}
<input type="text" onChange={(e) => setWrite(e.target.value)} />
{/* 글발행을 누르면 그 저장한 걸 글제목 배열에 추가 */}
<button onClick={() => {
let temp;
temp = [...글제목];
temp.push(write);
글제목변경(temp);
let like;
like = [...따봉];
like.push(0);
따봉변경(like);
console.log(따봉);
}}>글 발행</button>
{
modal === true ? <Modal 글제목={글제목} 글제목변경={글제목변경} title={title} /> : null
}
</div>
);
}
function Modal(props) {
return (
<div className="modal">
<h4>{props.글제목[props.title]}</h4>
<p>날짜</p>
<p>상세내용</p>
<button onClick={() => {
let copy = [...props.글제목];
copy[0] = '여자 코트 추천';
props.글제목변경(copy);
}}>글수정</button>
</div>
)
}