Publish to my blog (weekly)

    • Concretely, a higher-order component is a function that takes a component and returns a new component.
    • Whereas a component transforms props into UI, a higher-order component transforms a component into another component.
    • HOCs are common in third-party React libraries, such as Redux's connect and Relay's createContainer.
    • // This function takes a component... function withSubscription(WrappedComponent, selectData) {  // ...and returns another component...  return class extends React.Component {  constructor(props) {  super(props);  this.handleChange = this.handleChange.bind(this);  this.state = {  data: selectData(DataSource, props)  };  }   componentDidMount() {  // ... that takes care of the subscription...  DataSource.addChangeListener(this.handleChange);  }   componentWillUnmount() {  DataSource.removeChangeListener(this.handleChange);  }   handleChange() {  this.setState({  data: selectData(DataSource, this.props)  });  }   render() {  // ... and renders the wrapped component with the fresh data!  // Notice that we pass through any additional props  return <WrappedComponent data={this.state.data} {...this.props} />;  }  }; }
    • Rather, an HOC composes the original component by wrapping it in a container component. An HOC is a pure function with zero side-effects.
    • If this argument is specified, the new component will subscribe to Redux store updates.
    • The results of mapStateToProps must be a plain object, which will be merged into the component’s props.
    • This means that any time the store is updated, mapStateToProps will be called.
    • If you don't want to subscribe to store updates, pass null or undefined in place of mapStateToProps.
    • it will be called with the store state as the first parameter
    • taking two parameters
    • the props passed to the connected component as the second parameter
    • The mapStateToProps function takes a single argument of the entire Redux store’s state and returns an object to be passed as props. It is often called a selector.
    • If an object is passed, each function inside it is assumed to be a Redux action creator.
    • An object with the same function names, but with every action creator wrapped into a dispatch call so they may be invoked directly, will be merged into the component’s props.
    • If a function is passed, it will be given dispatch as the first parameter.
    • It’s up to you to return an object that somehow uses dispatch to bind action creators in your own way.
    • If your mapDispatchToProps function is declared as taking two parameters, it will be called with dispatch as the first parameter and the props passed to the connected component as the second parameter,
    • will be re-invoked whenever the connected component receives new props
    • If specified, it is passed the result of mapStateToProps(), mapDispatchToProps(), and the parent props.
    • Inject just dispatch and don't listen to store
    • Inject dispatch and todos
    • Inject todos and all action creators
    • Inject todos and all action creators (addTodo, completeTodo, ...) as actions
    • Inject todos and a specific action creator (addTodo)
    • Inject todos, todoActionCreators as todoActions, and counterActionCreators as counterActions
    • Inject todos, and todoActionCreators and counterActionCreators together as actions
    • Inject todos of a specific user depending on props
    • Inject todos of a specific user depending on props, and inject props.userId into the action
    • mergeProps
    • mergeProps
    • reducer를 여러개로 분리하여 작성 할 땐, 서로 직접적인 관계가 없어야 합니다.
    • 이 함수의 리턴값은 특정 컴포넌트 클래스의 props 를 store의 데이터에 연결시켜주는 또 다른 함수를 리턴합니다.
    • 리턴된 함수에 컴포넌트를 인수로 넣어 실행하면, 기존 컴포넌트를 수정하는게 아니라 새로운 컴포넌트를 return 합니다.
    • You'll notice that this guide does not use the terms "server" and "client". Why? You could use this server to server, client to client, it doesn't matter. Instead you have a "sender" and a "receiver". The "sender" can emit something, the "receiver" listens for the emit and may decide to emit something back in response. The "sender" can also request something from the "receiver" requiring a response of either successType or failureType
    • 소켓 채널에서 메시지를 받아 액션을 다시 Dispatch 하거나
    • 다른 액션을 기다리거나
    • 에러 처리 혹은 또 다른 비동기 처리 등의 많은 작업을 손쉽게 처리
    • The interesting component is the “race” command. Straight after the user login the “task” begins the execution of a passed function, until the action ‘STOP_WEBSOCKET’ is fired. And this is first fired when e.g. the user pushed log out button.
    • [call(externalListener, socketChannel), call(internalListener, socket)]
    • The fisrt param function externalListener is the Saga channel listening to the external websocket server and processing the incoming data.
    • The second one, internalListener, is a generator function listening to user commands, for example button events, dropdown changes etc. Here is an example how this listener can be implemented:
    • 간결한 구문 params => {object:literal}을 사용한 객체 리터럴 반환은 예상대로 작동하지 않음을 명심하세요:
    • 이는 중괄호({}) 안 코드가 일련의 문(즉 foo는 라벨처럼 취급됩니다, 객체 리터럴 내 키가 아니라)으로 파싱(parse, 구문 분석)되기 때문입니다.
    • 객체 리터럴를 괄호로 감싸는 것을 기억하세요:
    • ({ foo: 1 });
    • Redux-saga is mainly described as a way of dealing with side-effects (asynchronous calls and so on) performed by an application.
    • Incoming actions from the store invoke a function that will dispatch later an other action back to the store.
    • With websockets, we won’t rely on incoming actions but on external event sources.
    • With the second pattern, we can take advantage of queueing all non-processed actions (inside requestChan).
    • eventChannel is a function that takes a subscriber to initialize the external event source (it means for us to connect to the websocket server).
    • a thunk is a subroutine used to inject an additional calculation into another subroutine. Thunks are primarily used to delay a calculation until it is needed, or to insert operations at the beginning or end of the other subroutine.
    • State is similar to props, but it is private and fully controlled by the component.
    • Clock is now defined as a class rather than a function.

        

      This lets us use additional features such as local state and lifecycle hooks.

        

    • These methods are called "lifecycle hooks".
    • Inside it, the Clock component schedules a UI update by calling setState() with an object containing the current time.
    • Thanks to the setState() call, React knows the state has changed, and calls render() method again to learn what should be on the screen.
    • React may batch multiple setState() calls into a single update for performance.
    • Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
    • (prevState, props) => ({  counter: prevState.counter + props.increment })
    • function(prevState, props) {  return {  counter: prevState.counter + props.increment  }; }
    • But how do you know what should be its own component? Just use the same techniques for deciding if you should create a new function or object. One such technique is the single responsibility principle, that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents.
    • Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why.
    • Presentational
    • Container
    • Smart
    • Skinny
    • Stateful
    • Dumb
    • Fat
    • Pure
    • Components
    • Screens
      • Are concerned with how things look.
      • May contain both presentational and container components** inside, and usually have some DOM markup and styles of their own.
      • Often allow containment via this.props.children.
      • Have no dependencies on the rest of the app, such as Flux actions or stores.
      • Don’t specify how the data is loaded or mutated.
      • Receive data and callbacks exclusively via props.
      • Rarely have their own state (when they do, it’s UI state rather than data).
      • Are written as functional components unless they need state, lifecycle hooks, or performance optimizations.
      • Examples: Page, Sidebar, Story, UserInfo, List.
      • Are concerned with how things work.
      • May contain both presentational and container components** inside but usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.
      • Provide the data and behavior to presentational or other container components.
      • Call Flux actions and provide these as callbacks to the presentational components.
      • Are often stateful, as they tend to serve as data sources.
      • Are usually generated using higher order components such as connect() from React Redux, createContainer() from Relay, or Container.create() from Flux Utils, rather than written by hand.
      • Examples: UserPage, FollowersSidebar, StoryContainer, FollowedUserList.
      • 애플리케이션의 상태를 저장하고;
      •  
      • getState()를 통해 상태에 접근하게 하고;
      •  
      • dispatch(action)를 통해 상태를 수정할 수 있게 하고;
      •  
      • subscribe(listener)를 통해 리스너를 등록합니다.
    • let store = createStore(todoApp);
    • 만약 데이터를 다루는 로직을 쪼개고 싶다면, 여러개의 스토어 대신 리듀서 조합을 사용할 수 있습니다.
    • 서버에서 실행중인 Redux 애플리케이션의 상태와 일치하도록 클라이언트의 상태를 채워줄때 유용합니다.
    • createStore()의 두번째 인수로 초기 상태를 지정
    • 이 시점에서 여러분은 리듀서와 액션 생산자들을 위한 테스트를 작성할 수 있습니다. 이들은 단지 함수이기 때문에 아무것도 모조(mock)할 필요가 없습니다. 이들을 호출하고, 반환하는 것들을 검증하세요.
    • 이것을 리듀서 조합이라고 부르고, 이것이 Redux 앱을 만드는 기본 패턴이 됩니다.
    • 여러분이 이 형태의 함수를 Array.prototype.reduce(reducer, ?initialValue)로 넘길 것이기 때문에 리듀서라고 부릅니다
      • 여러분이 절대로 리듀서 내에서 하지 말아야 할 것들은:

         
           
        • 인수들을 변경(mutate)하기;
        •  
        • API 호출이나 라우팅 전환같은 사이드이펙트를 일으키기;
        •  
        • Date.now()Math.random() 같이 순수하지 않은 함수를 호출하기.
    • import * as reducers from './reducers';  const todoApp = combineReducers(reducers);
    • Object.assign에 관하여
       

      Object.assign()은 ES6의 일부이지만, 대부분의 브라우저에서 구현되지 않았습니다. 폴리필을 사용하거나 Babel 플러그인이나 _.assign()같이 다른 라이브러리의 헬퍼를 사용해야 합니다.

    • Redux는 todoApp이 위에서 했던것과 동일한 보일러플레이트 로직을 지원하는 combineReducers()라는 유틸리티를 제공합니다. 이를 이용하면 todoApp을 이렇게 재작성할 수 있습니다:
    • combineReducers()가 하는 일은 여러분의 리듀서들을 키에 따라 선택해서 잘라낸 상태들로 호출하고 그 결과를 다시 하나의 객체로 합쳐주는 함수를 만드는 것 뿐입니다
    • Redux는 처음에 리듀서를 undefined 상태로 호출합니다. 그때가 초기 상태를 반환할 기회입니다:
    • The inner function receives the store methods dispatch and getState as parameters.
    • An action creator that returns a function to perform asynchronous dispatch:
    • dispatch =>setTimeout(() =>// Yay! Can invoke sync or async actions with `dispatch`  dispatch(increment());  }, 1000);  };
    • An action creator that returns a function to perform conditional dispatch:

       
    • (dispatch, getState) =>const { counter } = getState();   if (counter % 2 === 0) {  return;  }   dispatch(increment());  };
    • 리듀서는 그저 이전 상태와 액션을 받아 다음 상태를 반환하는 순수 함수
    • 저장할 수 있고
    • 기록을 남길 수 있고
    • 시리얼라이즈할 수 있으며
    • 테스트나 디버깅을 위해서 재현하
    • 실행취소/다시실행(undo/redo)을 손쉽게 구현
    • 빠른 개발 사이클을 위해 개발중인 애플리케이션의 상태를 저장
    • 하나의 상태 트리만을 가지고 있기 때문에 디버깅에도 용이할 것
    • 애플리케이션의 모든 상태는 하나의 스토어 안에 하나의 객체 트리 구조로 저장됩니다.
    • 상태를 변화시키는 유일한 방법은 무슨 일이 벌어지는 지를 묘사하는 액션 객체를 전달하는 방법뿐입
    • 액션에 의해 상태 트리가 어떻게 변화하는 지를 지정하기 위해 프로그래머는 순수 리듀서를 작성해야합니다.
    • 범용적인 애플리케이션(universal application, 하나의 코드 베이스로 다양한 환경에서 실행 가능한 코드)을 만들기 쉽게 만들 수 있습니다
    • 액션은 그저 평범한 객체
    • 시리얼라이즈되거나(serialized)
    • 수화되어(hydrated)
    • [...state, {  text: action.text,  completed: false  }];
    • [  ...state.slice(0, action.index),  Object.assign({}, state[action.index], {  completed: true  }),  ...state.slice(action.index + 1)  ];
    • let reducer = combineReducers({ visibilityFilter, todos });
    • let store = createStore(reducer);
    • 각각의 액션이 전체 애플리케이션의 상태를 어떻게 변경할지 결정하는 특별한 함수인 리듀서를 작성합니다.
    • 뷰 바인딩 라이브러리(예를 들어 React Redux)를 사용합니다.
    • let store = createStore(counter)

Posted from Diigo. The rest of my favorite links are here.

댓글

이 블로그의 인기 게시물

Publish to my blog (weekly)

Publish to my blog (weekly)