김상욱 저
팀 페리스 저/최원형,윤동준 공역
공봉식 저 저
한선관,이정원,장명현 저
웹 퍼블리셔를 준비하면서 html css 자바스크립트 제이쿼리 그 다음은 리액트라고 생각만 하고 있었지
어려울까봐 도전하기 힘들었었는데 이번에 책을 보면서 기본적인 내용들을 습득할 수 있었어서 너무 좋았습니다!
항상 생각하지만 두잇 시리즈는 기초부터 응용까지 쉽게 알려주셔서 너무 좋아요ㅠㅠ
공부하면서 취뽀하게 되어서.. 당장은 리액트를 쓸일이 없어지는 바람에
홈페이지에 올라왔던 소스들 훑어보고, 책 끝까지 눈으로 쓱슥 읽어 내는 정도로 마무리 했는데도
확실히 공부하기 전 후가 다른게 느껴집니다! ㅋㅋ 일단은 기본적인 것들은 아는 정도가 되었느니
회사에서 리액트가 필요할때 다시 공부 시작해야겠어요!
최근 리액트를 할일이 있어 이책을 구매했습니다.
Do it series를 많이 봤던터리, 가단하게 개념 잡고자..
결과는 대 실망...
"책 오류 수정" 어마어마하다.. 도저히 책의 내용을 실행해 볼수가 없다, JS의 특성상 version업에 빨라서 그럴수 있다고 치더라도... 이책은 너무하다. 옆에 저자가 있으면 던저주고 이렇게 말하고 싶다 "이런 책을 가지고 Do it 하라고??" 절대 비추... Do it 도 믿을게 못되는군... 이런책을 출판해서 아직도 팔고 있다니.. 대실망.
====== 이하가 git hub에 저자가 올린 오탈자 ======
p.27 nvm으로 노드제이에스 설치하기
현재 현업에서 가장 많이 사용하는 노드제이에스의 버전이 8 10이기 때문입니다.
nvm install 8.10.0
nvm install 10.10.0
nvm use 8.10.0
nvm use 10.10.0
> node -v
10.10.0
p.28 1. yarn 설치하기
윈도우 사용자의 경우 공식 홈페이지 [ https://classic.yarnpkg.com/en/docs/install#windows-stable ] 에서 다운로드 받아 설치 가능합니다
p.28 2. create-react-app 설치하기 (2번 영역 전체 삭제)
yarn global add create-react-app
p.28 3. 리액트 앱 생성하기
이 책은 create-react-app 버전 2.1.7을 기준으로 작성되었습니다.
> yarn create react-app do-it-example --scripts-version 2.1.7
p.30 react-scripts 버전 수정
"react-scripts": "2.1.1"
"react-scripts": "2.1.7"
p.43 예제 코드 6번 항목
var args = Array.prototype.slice.call(this, arguments);
var args = Array.prototype.slice.call(arguments);
p.44 예제 코드 7번 항목
func(...args) { var [first, ...others] = args; }
function func(...args) { var [first, ...others] = args; }
p.70 (Promise코드와 관련하여)
(실제 Promise클래스와 약간의 차이는 있습니다.)
(개략적인 Promise코드 구조에 대해 이해를 돕고자 추가된 코드로 실제 Promise클래스와 차이가 있습니다. 아래 코드는 사용하지 말고 내장된 Promise를 사용하여 구동해주세요.)
// 아래 코드는 이해를 돕기 위한 코드입니다. 실제 코드와는 다르니 내장된 Promise를 사용해주세요.
class Promise {...}
p.92 (문장에 App.jsx파일 명명 설명 추가)
App 컴포넌트의 내용을 모두 지우고 다음을 입력해보세요. 여기서부터 App.js는 App.jsx로 변경하여 사용하겠습니다.
p.112 정답 코드
this.setState((count) => { count: count + 1; });
중괄호{} 앞뒤로 괄호()가 포함되어야 합니다. 또한 인자 count 양쪽으로 중괄호{}를 포함하여 객체 추출식으로 state값 중 count값을 추출해야합니다.
this.setState(({ count }) => ({
count: count + 1,
}));
참조: https://github.com/justinpark/justin-do-it-react/blob/master/src/03/Counter.jsx#L13
p.146 예제 코드
constructor에 정의된 window.addEventListener(...) 구문을 componentDidMount 함수 안으로 옮기셔야 초기 스크롤 시 undefined 오류가 발생하지 않습니다.
constructor(props) {
super(props);
this.setRef = this.setRef.bind(this);
this.checkPosition = this.checkPosition.bind(this);
}
// ...
componentDidMount() {
window.addEventListener('scroll', this.checkPosition);
this.checkPosition();
}
p.154 스토리북 설치
이 책은 스토리북 버전 5.2를 기준으로 작성되었습니다.
> yarn add --dev @storybook/react@5.2.6
p.161 addon-actions 설치
> yarn add --dev @storybook/addons@5.2.6 @storybook/addon-actions@5.2.6
p.163 addon-jsx 설치
> yarn add --dev storybook-addon-jsx@7.1.13
p.200 테스트 코드 실행
./src/App.test.js 파일을 삭제한 다음 실행하세요.
(App.test.js파일을 삭제하지 말고 실행하세요.)
p.201 <Input> 테스트 코드
expect 예제 한줄 추가
...
ReactDOM.unmountComponentAtNode(div);
expect(React.isValidElement(<Input />)).toBeTruthy();
4번 항목 예제에도 추가
...
ReactDOM.unmountComponentAtNode(div);
expect(React.isValidElement(<Input name="test_name" />)).toBeTruthy();
p.203 3번 항목 테스트 코드 파일 명명 (3쇄 요청)
테스트 코드 파일의 이름은 '~_spec.jsx' '~.test.jsx'로 짓겠습니다.
참고 파일: /src/tests/04/Input_spec.jsx
참고 파일: /src/tests/04/Input.test.jsx
p.204 참조 파일 경로에 오타가 있습니다 (3쇄 요청)
참고 파일: /src/tests/04/Input_spec.jsx
참고 파일: /src/__tests__/04/Input.test.jsx
p.207 참조 파일 경로에 오타가 있습니다
참고 파일: /src/tests/04/Input_spec.jsx
참고 파일: /src/__tests__/04/Input.test.jsx
7번 항목
> yarn test ./src/tests/03/Input_spec.jsx
> yarn test ./src/__tests__/04/Input.test.jsx
p.208 참조 파일 경로에 오타가 있습니다.
참고 파일: /src/tests/04/Input_spec.jsx
참고 파일: /src/__tests__/04/Input.test.jsx
p.209 참조 파일 경로에 오타가 있습니다.
참고 파일: /src/tests/04/Input_spec.jsx
참고 파일: /src/__tests__/04/Input.test.jsx
p.210 참조 파일 경로에 오타가 있습니다.
참고 파일: /src/tests/04/Input_spec.jsx
참고 파일: /src/__tests__/04/Input.test.jsx
p.211 참조 파일 경로에 오타가 있습니다.
참고 파일: /src/tests/04/Input_spec.jsx
참고 파일: /src/__tests__/04/Input.test.jsx
p.212 참조 파일 경로에 오타가 있습니다. (3쇄 요청)
참고 파일: /src/tests/04/Text_spec.jsx
참고 파일: /src/__tests__/04/Text.test.jsx
p.214 참조 파일 경로에 오타가 있습니다.
참고 파일: /src/tests/04/Text_spec.jsx
참고 파일: /src/__tests__/04/Text.test.jsx
p.216 참조 파일 경로에 오타가 있습니다.
참고 파일: /src/tests/04/Text_spec.jsx
참고 파일: /src/__tests__/04/Text.test.jsx
p. 221 참조 파일 경로에 오타가 있습니다.
참조파일: ./src/tests/04/CheckoutBox_spec.jsx
참조파일: ./src/__tests__/04/CheckBox.test.jsx
7번 코드 오류 (required -> test_name) expect(changeStub).toHaveBeenCalledWith('required', true);
expect(changeStub).toHaveBeenCalledWith('test_name', true);
8번 코드 오류 (required -> test_name) expect(changeStub).toHaveBeenCalledWith('required', false);
expect(changeStub).toHaveBeenCalledWith('test_name', false);
p.231 05-1-compose코드에 오타가 있습니다 (3쇄 요청)
return funcArry.reduce(
return funcArr.reduce(
p. 248 아래쪽 예제코드
WrappedComponent 옆의 전개 연산자 변수가 prop이 아닌 otherProps 으로 변경해야합니다.
<WrappedComponent {...props} />
<WrappedComponent {...otherProps} />
p.261 코드 수정
function Component() {
return null;
}
const ComponentWithX = withX(Component);
const ComponentWithXandY = withY(ComponentWithX);
const ComponentWithXandYandZ = withZ(ComponentWithXandY);
// 또는
const ComponentWithWYZ = withZ(withY(withX(Component)));
p.261 마지막 compose관련 설명 추가
05-1에서 직접 구현한 compose()함수는 사실 recompose 라이브러리에서 제공했던 것이죠. (추가 부분)
(다만 recompose의 경우 compose의 경우 적용 순서가 반대 반향인 "오른쪽에서 왼쪽 방향"으로 진행되는 차이가 있습니다. 이는 프로퍼티 전달 방향이 뒤쪽으로 진행되는 것과 관련있습니다.)
p.262 코드 예제
import compose from 'recompose/compose';
const withXYZ = compose(withZ, withY, withX);
const ComponentWithXYZ = withXYZ(Component);
// 혹은
// const compose(withZ, withY, withX)(Component);
(아래쪽 코드)
import compose from 'recompose/compose';
import withLoading from './withLoading';
import withState from' recompose/withState';
const withLoadData = withState('isLoading', 'setIsLoading', false);
function Component() {
return '완료(컴포넌트 출력)';
}
const ComponentWithLoading = withLoading('로딩중')(Component);
const ComponentWithLoadData = withLoadData(Component);
const withLoadingAndLoadData = compose(withLoadData, withLoading('로딩중'));
// 조합이 올바르지 못한 예: compose(withLoadData, withLoading)
// 올바르지 못한 예: compose(withLoading('로딩중'), withLoadData)
export const ComponentWithBoth = withLoadingAndLoadData(Component);
// 혹은 compose(withLoadData, withLoading('로딩중'))(Component);
p. 263 (3쇄 요청)
(2) withLoadingData('로딩 중')을 먼저 조합하면 withLoadingData withLoadData의 isLoading 프로퍼티가 withLoading 하이어오더 컴포넌트에 전달되지 않으므로 주의해야 합니다.
p. 275 설명 (3쇄 요청)
주석 1번 ButtonWithContext는 지면 부족으로 코드가 누락되었습니다. 다음 참조 파일을 참조하여 추가해주세요.
참조: https://github.com/justinpark/justin-do-it-react/blob/master/src/06/ButtonWithContext.jsx
p. 279 예제코드
Button 임포트 부분 추가
import ButtonWithLoadingContext from './ButtonWithLoadingContext';
import Button from '../04/Button';
function TableComponent() 아래에 중복 선언된 TableComponent부분 삭제
const TableComponent = () =>
p.279 (3쇄 요청)
ButtonWithLoadingContext의 출력 메시지를 label 프로퍼티로 변경
버튼
<ButtonWithLoadingContext label="버튼" />
상태 변경
<ButtonWithLoadingContext label="상태 변경" />
참조: https://github.com/justinpark/justin-do-it-react/blob/master/src/06/HomePageWithProvider.jsx
p. 282 공급자 반환하는 커링 함수 만들기 설명 부분
this.state를 보면 [contextKey]라고
getChildContext()를 보면 [contextKey]라고
p. 284 예제코드
HomePageComponentWithTwoProvider 클래스 선언 앞에 export 추가
export class HomePageComponentWithTwoProvider extends PureComponent {...}
p.317 예제코드
위쪽의 두개의 중괄호}} 중 앞쪽 괄호는 일반 괄호로 변경)}해야 합니다.
<Consumer>
{({ openModal }) => (
<Button onPress={openModal} />
)}
</Consumer>
p.343 참조 파일 경로에 오타(jsx)가 있습니다.
참조파일: ./src/07/reducers/userReducer.jsx
참조파일: ./src/07/reducers/userReducer.js
p.348 참조 파일 경로에 오타(jsx)가 있습니다.
참조파일: ./src/07/reducers/loadingReducer.jsx
참조파일: ./src/07/reducers/loadingReducer.js
p. 352 예제코드 경로
참조파일: ./src/07/collectionActions01.js
참조파일: ./src/07/actions/collectionActions01.js
p. 358 collectionReducer 예제 코드
collectionActions파일은 앞의 collectionActions01과 collectionActions02의 코드를 모두 포함한 파일입니다.
import { SET_COLLECTION, SET_AGE } from '../actions/collectionActions';
p.431
import * as serviceWorker from './serviceWorker'; 강조 색상 삭제
p.517
TradeCoinPage.jsx 예제 코드의 handleSubmit 부분에서 createTransaction을 this.props에서 추출하는 부분이 생략되어 있습니다.
const { name, code } = this.props;
handleSubmit(values, closeModal) {
const { name, code, createTransaction } = this.props;
...
p.517 빗줄 굶은 색상으로 변경 요청 (3쇄 요청)
~~Api .post('/transactions', formValues) .then(() => closeModal());
=====================
이걸 책이라고 팔 수 있나?
리액트를 이제 배우고 있는 사람인데요... 이 책은 애증의 책이네요..
무엇보다도 예제가 다듬어지지 않은게 아쉽습니다..
예제가... 저자가 실제로 프로젝트에서 사용하던 것들을 가져와서 넣은 것 같은 느낌이 납니다.
그래서 export는 빼고 실행하라고 하는 것도 있고... 실제로 코딩해보면 100ms 내로 키보드드로 입력해서 엔터를 쳐야하는 것도 나옵니다...
또한 간단한 예제인데 div에 쓸데없는 className도 있고..
이런것들이 초보자입장에서는 무지 헷깔립니다... 이게 왜 들어갔을까.. 이게 뭐지?? 필요한 건가?
참고파일명도 안맞는것도 있구요... jsx파일인지... js파일인지... 헷깔립니다.
저는 더 낮은 수준의 책을 읽고 돌아와서 다시 봤습니다. (아직 다 보지 못했습니다)
실제 저자가 사용하는 실무 작업환경과 라이브러리들을 보여주고 싶은 것 같다는 느낌을 받았습니다.
그래서 저같은 초보자들은 나아가기가 쉽지 않네요...
설명도.... 음.. 그리 쉽게 설명이 되어 있지 않습니다.. 제 기준엔 그러네요.
막 배우시는 분들에게는 추천드리기 어렵네요... 좀 실력이 있으신 분들이 보시면 좋을꺼 같아요...
자바 9년차 개발자입니다. 요즘 프로젝트를 하다보면 개발자들 사이에서 가장 많이 나오는 기술이 리액트라는 자바스크립트 라이브러리입니다. 일반 자바스크립트나, jquery는 많이 사용했지만 리액트라고 하면 많이 생소해서, 책을 고르던 도중 이책이 제일 마음에 들어 구매했습니다.
책도 이해하기 쉽게 구성되어 있어, 재미있게 읽었습니다. 하지만 프로그래밍 책은 반복적인 실습이 가장 중요합니다. 계속 반복적으로 읽어야 겠습니다