React (생활코딩 ver.2022)

장윤희·2022년 8월 3일
0

React

목록 보기
1/3
post-thumbnail

1-3강 요약 (22.08.02)

환경설정, 수정 및 배포

npx serve -s build(파일위치)
: build폴더안에 있는 index.html을 서비스해주는 웹서버 실행

-s : 사용자가 어떤 경로로 들어오든 index.html을 서비스

4-6강 요약 (22.08.03)

리액트는 사용자 정의태그를 만드는 기술이다.

컨퍼넌트 생성하기

function Header(){ //대문자로 시작
	return <header>
    <h1><a href="/">WEB</a></h1>
    </header>
}
function Nav(){ //대문자로 시작
	return <nav>
    <ol>
   		<li><a href="/read/1">html</a></li>
    	<li><a href="/read/1">html</a></li>
    	<li><a href="/read/1">html</a></li>
    </ol>
   </nav>
}
function Article(){ //대문자로 시작
	return <article>
    	<h2>welcome</h2>
        hello,web
      </article>
}
function App(){
	return (
    	<div>
        	<Header></Header> //컨퍼넌트
            <Nav></Nav> //컨퍼넌트
            <Article></Article> //컨퍼넌트
        </div>
    );
}

export default App;

사용자정의 태그(함수)를 만들때는 시작이 무조건 대문자이여한다.

속성 이용하기

속성을 PROP라고 한다.
속성을 사용하고 싶으면 넣고싶은 값을 함수의 파라미터 값(props)로 넣는다.
함수안의 html안에서 중괄호로 감싸주어 이를 속성으로 받는다. ex){props.title}
이런식으로 하면 하나의 함수로 값이 달라지는 html 로 만들 수 았다

function Nav(props){ //props를 파라미터값으로 넣는다
	const lis = []
      for(let i=0; i<props.topics.length; i++){
            let t = props.topics[i];
            lis.push(<li key={t.id}>
            <a href="{/read/"+t.id}>{t.title}</a>
          </li>)
      }
      return <nav>
      <ol>
          {lis}
      </ol>
   </nav>
}
function App(){
	const topics = [
    	{id:1, title:'html', body:'html is...'},
        {id:1, title:'css', body:'css is...'},
        {id:1, title:'js', body:'js is...'}
    ]
    return(
    	<div>
        	<Header title="REACT"></Header>
            <Nav topics={topics}></Nav>
            <Article title="welcome" body="Hello, WEB"></Article>
        </div>
    );
}

export default App;

위의 예시는 li를 topics라는 변수안에 배열로 넣고 length길이만큼 for문을 돌려서 li태그를 생성한다.
{t.id}, {t.title}라는 데이터 값을 지정해 주어서 데이터 값이 달라도 하나의 함수로 만들 수 있다.

이벤트를 가진 컨퍼넌트 만들기

function Nav(props){
	const lis = []
      for(let i=0; i<props.topics.length; i++){
            let t = props.topics[i];
            lis.push(<li key={t.id}>
            <a href="{/read/"+t.id} onClick={event=>{
            	event.preventDefault();
                porps.onChangeMode(event.target.id);
            }}>{t.title}</a>
          </li>)
      }
      return <nav>
      <ol>
          {lis}
      </ol>
   </nav>
}
function App(){
	const topics = [
    	{id:1, title:'html', body:'html is...'},
        {id:1, title:'css', body:'css is...'},
        {id:1, title:'js', body:'js is...'}
    ]
    return(
        <div>
        	<Header title="WEB" onchangeMode={()=>{
            	alert('Header');
            }}></Header>
            <Nav topics={topics} onchangeMode={()=>{
            	alert(id);
            }}></Nav>
            <Article title="welcome" body="Hello, WEB"></Article>
        </div>
    );
}

export default App;

자동으로 생성한 태그에는 key가 필요하다.
key값은 element에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야한다.
key는 다른 항목들 사이에서 고유하게 식별할 수 있는 것을 사용한다.
이벤트객체를 처음에 넣는다. (es6문법 사용)
event.preventDefault(); 로 이벤트 리로딩을 막는다.

7-9강 요약 (22.08.04)

State

function Nav(props) {
	const lis = [];
	for (let i = 0; i < props.topics.length; i++) {
		let t = props.topics[i];
		lis.push(
			<li key={t.id}>
				<a
                  id={t.id}
                  href={'/read/' + t.id}
                  onClick={(event) => {
                    event.preventDefault();
                    props.onChangeMode(Number(event.target.id));
                  // 태그의 속성으로 넘기면 숫자가 문자가 된다 그래서 숫자로 컴포팅해줘야함 **
                  }}
                >
				{t.title}
				</a>
			</li>
		);
	}
	return (
		<nav>
			<ol>{lis}</ol>
		</nav>
	);
}
function App() {
	// const _mode = useState('welcome'); state의 초기값
	//const mode = _mode[0]; 0번째 원소로 읽음
	//const setMode = _mode[1]; 1번째원소인 setMode를 통해 mode를 바꿀 수 있음
	const [mode, setMode] = useState(''); //위의 축약형 보통 이걸 사용
	const [id, setId] = useState(null); //선택한 값이 id와 일치하는지 보기위해
	const topics = [
		{ id: 1, title: 'html', body: 'html is ...' },
        { id: 2, title: 'css', body: 'css is ...' },
        { id: 3, title: 'javascript', body: 'javascript is ...' },
		];
	let content = null;
 	if (mode === 'WELCOME') { 
		content = <Article title="welcome" body="Hello, WEB"></Article>;
	} else if (mode === 'READ') {
		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 = <Article title={title} body={body}></Article>;
	}
	return (
  		<div className="App">
   			<Header
				title="WEB"
                onChangeMode={() => {
                  // mode = 'WELCOME'; 읽을때
                  setMode('WELCOME'); //바꿀때
                }}
              ></Header>
              <Nav
				topics={topics}
                onChangeMode={(_id) => {
                  setMode('READ');
                  setId(_id);
                }}
              ></Nav>
			{content}
		</div>
	);
}
        
 export default App;

mode의 값이 바뀌더라도 App은 새로 로딩되지않기때문에 state를 사용한다.
useState의 인자는 state의 초기값
useState는 배열 0번째는 상태의 값을 읽을때 쓰는 데이터
1번째는 상태의 값을 변경할때 쓰는 함수

CREATE (상세보기만들기)

function Nav(props) {
	const lis = [];
    for (let i = 0; i < props.topics.length; i++) {
      let t = props.topics[i];
      lis.push(
        <li key={t.id}>
          <a
            id={t.id}
            href={'/read/' + t.id}
            onClick={(event) => {
              event.preventDefault();
              props.onChangeMode(Number(event.target.id));
            }}
          >
            {t.title}
          </a>
        </li>
      );
    }
    return (
      <nav>
        <ol>{lis}</ol>
      </nav>
	);
}
function Create(props){
	return <article>
      <h2>Create</h2>
      <form onSubmit={event=>{
      //onSubmit은 submit버튼을 눌렀을때 form에서 발생하는 이벤트
        event.preventDefault();
        const title = event.target.title.vlaue; //여기서 event.target는 form태그
        const body = event.target.body.vlaue;
        props.onCreate(title, body);
      }}>
        <p><input type="text" name="title" placeholder="title"/></p>
        <p><textarea name="body" placeholder="body"></textarea></p>
        <p><input type="submit" value="Create"/></p>
      </form>
    </article>
  }
  function App() {
    const [mode, setMode] = useState('');
    const [id, setId] = useState(null);
    const [nextId, setNextId] = useState();
    const [topics, setTopics] = useState([ //읽기와 쓰기 인터페이스 추가
      { id: 1, title: 'html', body: 'html is ...' },
      { id: 2, title: 'css', body: 'css is ...' },
      { id: 3, title: 'javascript', body: 'javascript is ...' },
    ]);
    let content = null;
    if (mode === 'WELCOME') {
      content = <Article title="welcome" body="Hello, WEB"></Article>;
    } else if (mode === 'READ') {
      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 = <Article title={title} body={body}></Article>;
    }else if(mode === 'CREATE'){ //mode가 CREATE 일때
      content = <Create onCreate={(_title, _body)=>{
        const newTopic = {id:nextId, title:_title, body:_body}
        const newTopics = [...topics] //
        topics.push(newTopic);
        setTopics(newTopics);
        //현재와 복제본이 다르다면 컨퍼넌트 새로 렌더링
        setMide('READ'); //새로 만든것의 상세페이지 보기
        setId(nextId); //현재 추가한 글의 id 지정
        setNextId(nextId+1); //다음에 추가할 글을 위해 id지정
      }}></Create>
    }
    return (
      <div className="App">
        <Header
          title="WEB"
          onChangeMode={() => {
            setMode('WELCOME');
          }}
        ></Header>
        <Nav
          topics={topics}
          onChangeMode={(_id) => {
            setMode('READ');
            setId(_id);
          }}
        ></Nav>
        {content}
        <a href="/create" onClick={event=>{ //생성버튼 mode가 CREATE로 바뀜
          event.preventDefault();
          setMode('CREATE');
        }}>Create</a>
      </div>
	);
}
  
export default App;

원시데이터타입(PRIMITIVE)

const [value, setValue] = useState(PRIMITIVE);
string, number, bigint, boolean, undefined, symbol, null

범객체(Object)

const [value, setValue] = useState(Object);
object, array

  • object의 경우
    newValue ={...value} //데이터를 복제한다
    newVlaue 변경 // 복제본 변경
    setValue(newValue) //변경된 복제본을 실행

  • array경우
    newValue =[...value] //데이터를 복제한다
    newVlaue 변경 // 복제본 변경
    setValue(newValue) //변경된 복제본을 실행

  • 객체와 같이 복합적인 데이터일 경우
    const [value, setValue] = useState([1]);
    value.push(2); //오리지널 데이터를 바꿈
    setValue(value); //오리지널 데이터가 바뀌면서 현재와 같아서 컨퍼넌트가 렌더링 안됨
    => 해결방법
    const [value, setValue] = useState([1]);
    newValue = [...value] //배열일 경우 대괄호
    newValue.push(2);
    setValue(newValue); //컨퍼넌트 다시 실행

UPDATE

UPDATE = CREATE + READ

function Nav(props) {
	const lis = [];
    for (let i = 0; i < props.topics.length; i++) {
      let t = props.topics[i];
      lis.push(
        <li key={t.id}>
          <a
            id={t.id}
            href={'/read/' + t.id}
            onClick={(event) => {
              event.preventDefault();
              props.onChangeMode(Number(event.target.id));
            }}
          >
            {t.title}
          </a>
        </li>
      );
    }
    return (
      <nav>
        <ol>{lis}</ol>
      </nav>
    );
}
function Create(props){
	return <article>
      <h2>Create</h2>
      <form onSubmit={event=>{
          event.preventDefault();
          const title = event.target.title.vlaue;
          const body = event.target.body.vlaue;
          props.onCreate(title,body);
      }}>
          <p><input type="text" name="title" placeholder="title"/></p>
          <p><textarea name="body" placeholder="body"></textarea></p>
          <p><input type="submit" value="Create"/></p>
      </form>
	</article>
}
function Update(props){
	const [title, setTitle] = useState(props.title);
    const [body, setBody] = useState(props.body);
    //props의 데이터를 state데이터로 환승
    return <article>
      <h2>Update</h2>
      <form onSubmit={event=>{
        event.preventDefault();
        const title = event.target.title.vlaue;
        const body = event.target.body.vlaue;
        props.onUpdate(title,body);
      }}>
        <p><input type="text" name="title" placeholder="title" value={title} onChange={event=>{
          setTitle(event.target.value); 
          //state는 컴포넌트로 바꿀 수 있다
          //키보드로 입력할때마다 새로 렌더링
          //가장 최근에 변경된 값을 받아와서 바꿈
        }}/></p>
        <p><textarea name="body" placeholder="body"value={body} onChange={event=>{
          setBody(event.target.value); //키보드로 입력할때마다
        }}></textarea></p>
        <p><input type="submit" value="Update"/></p>
      </form>
    </article>
}
function App() {
	const [mode, setMode] = useState('');
    const [id, setId] = useState(null);
    const [nextId, setNextId] = useState();
    const [topics, setTopics] = useState([
      { id: 1, title: 'html', body: 'html is ...' },
      { id: 2, title: 'css', body: 'css is ...' },
      { id: 3, title: 'javascript', body: 'javascript is ...' },
    ]);
    let content = null;
    let contextControl = null; //update를 위한 변수 생성
    if (mode === 'WELCOME') {
      content = <Article title="welcome" body="Hello, WEB"></Article>;
    } else if (mode === 'READ') {
      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 = <Article title={title} body={body}></Article>;
      contextControl =  <li><a href={"/update"+id} onClick={event=>{
        event.preventDefault();
        setMode('UPDATE');
      }}>Update</a></li>
    }else if(mode === 'CREATE'){
      content = <Create onCreate={(_title, _body)=>{
        const newTopic = {id:nextId, title:_title, body:_body}
        const newTopics = [...topics]
        topics.push(newTopic);
        setTopics(newTopics);
        //현재와 복제본이 다르면 새로 렌더링
        setMide('READ'); //새로 만든것의 상세페이지 보기
        setId(nextId);
        setId(nextId+1);
      }}></Create>
    }else if(moede === 'UPDATE'){ //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)=>{
        console.log(title, body);
        const newTopics = [...topics] //배열 복제
        const updatedTopic = {id:id, title:title, body:body}
        for(let i=0; i<newTopics.length; i++){
          if(newTopics[i].id === id){ //id가 일치하는 것이 현재 선택한 topic
            newTopics[i] = updatedTopic; //교체
            break;
          }
        } 
        setTopics(newTopics);
        setMode('READ');
      }}></Update>
    }
    return (
      <div className="App">
        <Header
          title="WEB"
          onChangeMode={() => {
            setMode('WELCOME');
          }}
        ></Header>
        <Nav
          topics={topics}
          onChangeMode={(_id) => {
            setMode('READ');
            setId(_id);
          }}
        ></Nav>
        {content}
        <ul>
          <li><a href="/create" onClick={event=>{
            event.preventDefault();
            setMode('CREATE');
          }}>Create</a></li>
         {contextControl}
        </ul>
      </div>
    );
  }
  
  export default App;

10강 요약 (22.08.05)

DELETE

contextControl =  <> //그룹핑하는 용도의 빈 태그
	<li><input type="button" value="Delete" onClick={()=>{
		const newTopics = [] //오리지널과는 다른 데이터
        for(let i=0; i<toptics.length; i++){
          if(topics[i].id !== id){
            newTopics.push(topics[i]); //일치하지 않는 topic만 push
          }
        }
		setTopics(newTopics);
        setMode('WELCOME');
		}} />
	</li>
 </>

참고자료
: https://www.youtube.com/watch?v=AoMv0SIjZL8&list=PLuHgQVnccGMCOGstdDZvH41x0Vtvwyxu7

profile
멋쟁이

0개의 댓글