주소 설계할 때 아래의 이미지처럼 만들 수 있습니다.
그렇다면 수정하기는 /boards/edit?
실무용 폴더구조를 만들 때, 여러패턴(방법)들이 있지만 리액트에서 사용하는 유명한 패턴으로는 container / presentational 패턴, hooks 패턴, atomic 패턴이 있습니다.
1. container / presentational (클래스형)
2. 훅스패턴= (useState..등 유즈 로 시작하는애들 기반으로 폴더 만들자) -> 함수형형식
3. 아토믹 패턴 (부품을 조금 더 체계화해보자)
container / presentational 패턴이란, 소스코드를 자바스크립트(기능)와 JSX (UI)로 나누는 방법을 의미합니다.
- container는 자바스크립트(기능) 부분을 의미
- presentational은 JSX(UI) 부분을 의미
위 파일을 2개의 파일로 나누는 방법은 아래와 같습니다.
파일을 나눴어도 실행될 때는 하나로 합쳐져서 실행 되어야 합니다.
하나로 합쳐서 실행하는 방법은 부모컴포넌트에 자식컴포넌트를 불러오는 것 입니다.
위와 같이 자식컴포넌트인 presenter를 부모 컴포넌트인 container에 불러와 하나로 합쳐 실행 하는 것 입니다.
반드시 기억해야하는 점은, 파일은 두개로 나뉘어져 있지만 실행시에는 pages에서 하나로 합쳐져서 실행된다는 점 입니다.
우리가 브라우저로 볼 수 있는 컴포넌트는 pages에 있는 index.js 뿐이기 때문에 하나로 합쳐둔 container를 pages에 가지고 와서 import 해주셔야 합니다.
💡 부모 컴포넌트와 자식 컴포넌트
→ import되어 불려가는 컴포넌트를 자식 컴포넌트라고 합니다.
반면 import하여 불러오는 컴포넌트를 부모 컴포넌트라고 합니다. 자식컴포넌트는 부모 컴포넌트 안에 포함되는 구조 입니다.
모든 페이지는 App컴포넌트에서 합쳐진다.
왼쪽 부모컴포넌트 , 오른쪽 자식 컴포넌트!
오른쪽 프리젠테더가 왼쪽 컨테이너로 불려와서 리턴 되고 연두색 박스처럼 다 하나로 보이게된다.
부모컴포넌트가 가지고있는 기능들을 자식컴포넌트에게 물려주는 변수또는 함수이다. 자식이 부모에게 줄 수는 없음. (리액터 데이터 흐름 : 단방향 관계)
어떻게? -> props 를 통해서!객체가 만들어진다고 보면 된다.
💡실습 코드 캡쳐
- 최종적으로 , 자식이 부모에게 임포트 되고 초ㅣ종적으로 앱에서 보이게 된다(연두색 박스)
컴포넌트를 2개로 나누면서 데이터와 기능의 연결고리가 끊어지게 됩니다.
이를 props가 연결해주게 되며, props란 부모 컴포넌트가 자식 컴포넌트에게 물려주는 변수/함수
를 의미합니다.
부모 컴포넌트가 props를 물려줄때는 객체로 묶어서 넘기게 됩니다.
자식 컴포넌트 태그의 propsName 잘 보기
//부모 컴포넌트 _ container 부분 const BoardWrite = ()=>{ const [writer, setWriter ] = useState() const handlechangeWriter = (e)=>{ writer = e.target.value setWriter(writer) } return( // 자식 컴포넌트 _ presenter 컴포넌트 // 본격적으로 props를 내려주는 부분입니다. <BoardWriteUI propsName={handlechangeWriter}/> ) }
위와 같이 props를 넘기게 되면, props = { propsName : handlechangeWriter } 형태의 객체로 넘어가게 됩니다. 또한 props는 여러개를 내려 줄 수 있습니다.
//자식컴포넌트 _ presenter 부분 //파라미터 부분에 props를 적어주셔야 받아 올 수 있습니다. const BoardWriteUI = (props)=>{ return( <Wrapper> <Writer type = "text" placeholder = "작성자를 적어주세요" // 본격적으로 props를 내려받는 부분입니다. onChange = {props.propsName} /> </Wrapper> ) }
파라미터 부분에 props를 적지 않으면 받아 올 수 없으니 주의 해주셔야 합니다.
또한 객체로 넘어오기 때문에 받아온 props를 사용하려면 객체의 속성을 꺼내오는 것 처럼 사용해주셔야 합니다. 따라서 props.propsName 형태로 사용해야 합니다.
데이터흐름이 단방향 구조
라고 합니다.
위 이미지처럼, import 해올 때 어떤것은 중괄호를 사용했고, 어떤것을 중괄호가 없었습니다.
중괄호의 사용 여부는 export를 하냐, export default를 사용하느냐에 따라 결정됩니다.
**export**
: 한 컴포넌트 내에서 여러개를 내보내기 때문에 중괄호를 사용해 필요한 것들만 import합니다. import할 때는 export한 이름 그대로 불러와야합니다.
**export default**
: 한 컴포넌트에서 한개만 내보내기 때문에 중괄호를 사용하지 않고 import 하게 됩니다. import 해올 때 export한 이름이 아니어도 괜찮습니다.
한 컴포넌트에서 한개만 emport했기 때문에 파일의 경로만 제대로 지정되면 됩니다.export를 한번에 묶고싶을 때는
import * as S from "경로"
를 사용합니다.
아래 이미지처럼 css를 작성해주었습니다!
💡 정리해보면, 이렇게 폴더를 쪼개놓으면 코드의 유지보수와 가독성에 유리합니다. 에러가 나도 어디서 에러가 난건지에 따라 해당 파일에 들어가서 바로 고쳐주면 해결이 쉽습니다!
css 문제
-> styles 파일
html 문제
-> 프리젠터 파일
자바스크립트 문제
-> 컨테이너 파일
페이지접속 문제
-> 페이지 파일
전체적인 이상함
> 앱 파일
import * as S from "경로"
를 사용하면 이전에 하나씩 적어주던 것보다 편리하다고 하셨는데, 그래도 이미지 처럼 S.RedInput
이렇게 하나씩 적어주어야 하는거면 똑같지 않나?????? 똑같이 하나씩 써줘야하는 것 같아서 뭐가 다른건가 궁금하다.오늘 과제는, 리액트 파일을 html, css, 자바스크립트 등 컴포넌트 단위로 쪼개주는 것이었다. 쉬울 줄 알았는데 에러의 연속이라 정신 나갈뻔 했지만ㅎㅎ 페어분들이 도와주셔서..진짜 이상한 에러도 한시간 반만에(?)🙄 잡았다고..한다 물론 내가 말고 페어분께서 :).....(괜쟈나 할 수 있어!!)
그래서 내가 만난 에러들과 실수들을 대충 정리해보자면
- 경로 설정 완전 이상하게 했음. 같은 파일안에 있는애는
../../../../
요따구 아니고./
해주면 바로 나옵니다.
-> 근데 도대체 위처럼 ../ ../ ../의 연속이었는데도 자동으로 나왔지..?(암튼 얘때문에 에러였음)- 괄호 안에
props
안썼음. -> 받아주는 자식페이지에서 꼭 써주기!- css
import
를 page 폴더에 (부모폴더 아님) 해줌- 다른 폴더에서 변수명 [qqq] 있으면 다른 변수명으로 바꿔주기
오타오타오타오타오타오타오타오타오타!!!!!!!!!!!!!!!!!!!!!!!!
- html 부분에 객체로 만들어서 넣어주기. { props.writer } 이런 형태!
근데 도저히 모르겠는데 에러메세지가 있었다. 자꾸 인트값 어쩌고 하는데 분명 잘 썼거든유.. 이거 수정 안해주었는데도 할튼 잘 마무리 하긴 했다.
혹시 몰라 적어놔야지(두개임)
1.
{"errors":[{"message":"Variable "$createProductInput" got invalid value "" at "createProductInput.price"; Int cannot represent non-integer value: ""","locations":[{"line":1,"column":41}],"extensions":{"code":"BAD_USER_INPUT","exception":{"stacktrace":["GraphQLError: Variable "$createProductInput" got invalid value "" at "createProductInput.price"; Int cannot represent non-integer value: """," at /newbizcode_backend_common/node_modules/graphql/execution/values.js:116:15"," at coerceInputValueImpl (/newbizcode_backend_common/node_modules/graphql/utilities/coerceInputValue.js:132:9)"," at coerceInputValueImpl (/newbizcode_backend_common/node_modules/graphql/utilities/coerceInputValue.js:106:34)"," at coerceInputValueImpl (/newbizcode_backend_common/node_modules/graphql/utilities/coerceInputValue.js:56:14)"," at coerceInputValue (/newbizcode_backend_common/node_modules/graphql/utilities/coerceInputValue.js:39:10)"," at _loop (/newbizcode_backend_common/node_modules/graphql/execution/values.js:109:69)"," at coerceVariableValues (/newbizcode_backend_common/node_modules/graphql/execution/values.js:121:16)"," at getVariableValues (/newbizcode_backend_common/node_modules/graphql/execution/values.js:50:19)"," at buildExecutionContext (/newbizcode_backend_common/node_modules/graphql/execution/execute.js:205:61)"," at executeImpl (/newbizcode_backend_common/node_modules/graphql/execution/execute.js:103:20)"]}}}]}
2.
<!DOCTYPE html><html><head><style data-next-hide-fouc="true">body{display:none}</style><noscript data-next-hide-fouc="true"><style>body{display:block}</style></noscript><meta name="viewport" content="width=device-width"/><meta charSet="utf-8"/><title>Application error: a client-side exception has occurred</title><meta name="next-head-count" content="3"/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills.js?ts=1679311184807"></script><script src="/_next/static/chunks/webpack.js?ts=1679311184807" defer=""></script><script src="/_next/static/chunks/main.js?ts=1679311184807" defer=""></script><script src="/_next/static/chunks/pages/_app.js?ts=1679311184807" defer=""></script><script src="/_next/static/chunks/pages/_error.js?ts=1679311184807" defer=""></script><script src="/_next/static/development/_buildManifest.js?ts=1679311184807" defer=""></script><script src="/_next/static/development/_ssgManifest.js?ts=1679311184807" defer=""></script>