July 12, 2021
const isItemSelected = (item) => {
const isInbox = item.selectedItem.type ....
const isFirstUsed = item.selectedItem...
if(isInbox || isFirstUsed){
return true
}
return false
}
// 이렇게 써보는 건?
const isItemSelected = (item) => {
const isInbox = item.selectedItem.type ....
const isFirstUsed = item.selectedItem...
return isInbox || isFirstUsed
} const checkPosts = async (postId: string) => {
await axios.get(...)
}
interface IPost = {
postId?: string,
creator: string,
title: string
}
const testPost: IPost = createPost({ ... })
checkPosts(testPost.id) // string type에 string | undefined를 전달하려 한다고 error!
checkPosts(testPost?.id ?? '') // 이렇게 써보는건 ?Ref forwarding은 component로 자식에세 ref를 전달할 때 사용하는 technique이다. 대부분의 app의 components에는 필요하지 않다. 하지만 몇 가지 컴포넌트의 경우 유용하게 사용되며 특히 재사용성이 높은 컴포넌트의 경우에 도움이 된다. 가장 자주 사용되는 시나리오들을 나열해보자.
Forwarding refs to DOM components
native button DOM element를 렌더하는 FancyButton 컴포넌트가 있다고 가정해보자.
function FancyButton (props) {
return <button className='fancy'>{props.children}</button>
}React 컴포넌트는 렌더된 output을 포함해서 구체적인 구현 방법을 숨기고 있다. ? FancyButton을 사용하는 다른 컴포넌트의 경우 주로 inner button DOM element의 ref을 가지고 있을 필요가 없다. 이건 컴포넌트가 각각의 DOM 구조에 너무 의존하는 걸 막을 수 있어서 좋다.
이런 캡슐화는 FeedStory 나 Comment 같은 application-level 컴포넌트를 구성하는데는 바람직하지만, FancyButton이나 MyTextInput 같은 재사용성이 높은 ‘leaf’ 컴포넌트를 구현하는데는 불편할 수 있다. 이러한 컴포넌트들은 어플리케이션 내에서 일반 DOM button이나 input 처럼 사용되는 경우가 많기도 하고 focus, selection, animation등을 다루기 위해서는 DOM 접근이 불가피하기 떄문이기도 하다.
Ref forwarding 은 어떤 컴포넌트들이 그들이 받는 ref를 child에게 전달해줄 때 사용하기 적합한 기능이다.
예를 들어, FancyButton은 React.forwardRef를 ref를 가져오기 위해서 사용하고 컴포넌트가 render 하는 DOM button에 전달한다.
const FancyButton = React.forwardRef((props, ref) => (
<button className='fancy'>{props.children}</button>
))
const ref = React.createRef()
<FancyButton ref={ref}>Click me!</FancyButton>이 방법으로 FancyButton을 사용하는 컴포넌트는 그 아래 존재하는 button DOM node의 ref를 가질 수 있고 필요하다면 직접 접근할 수 도 있다. - 마치 DOM button을 직접 사용하는 것 처럼!
위의 예제에서 어떤 일이 일어났는지 단계별로 확인해보자.
ref 라는 변수에 assign 한다.ref를 <FancyButton ref={ref}> 에게 JSX attribute로 전달한다.(props, ref) => ...ref를 Note 두번째 인자인
ref는 React.forwardRef 로 컴포넌트를 실행시켰을 때만 존재한다. 일반 function 컴포넌트는 ref arguments를 받지 않고 ref는 props로도 전달이 불가능하다. Ref forwarding은 DOM components에만 한정되지 않고, class component instances 들에서도 ref 전달이 가능하다!
Forwarding refs in higher-order components
이 technique은 HOC 컴포넌트에서도 유용하다. components의 props를 log 출력하는 HOC를 예로 들어보자.
function logProps (WrappedComponent) {
class LogProps extends React.Componet {
componentDidUpdate (prevProps) {
console.log('old props:', prevProps)
console.log('new props:', this.props)
}
render(){
return <WrappedComponent {...this.props}>
}
}
return LogProps;
}logProps HOC는 그 컴포넌트가 감싸는 컴포넌트에 모든 props를 전달한다. 그래서 render되는 output은 같다. 예를 들어, 이 HOC를 모든 props를 출력하기 위해 사용할 수 있다.
class FancyButton extends React.Component {
focust () {
///
}
// ...
}
// FancyButton을 export 하지 않고 LogProps를 export 한다. 하지만 결국 FancyButton이 Render 된다.
export default logProps(FancyButton)위의 예에는 한가지 주의 사항이 있다. refs는 전달되지 않는다는 점이다! 그 이유는 ref은 prop이 아니기 때문이다. key 처럼 React에 의해 다르게 handling 된다. 만약 HOC에 ref를 추가한다면, wrapped 컴포넌트가 아니라 ref는 가장 바깥의 container 컴포넌트를 가리킬 것이다.
이 의미는 FancyButton을 가리킬거라고 의도 했던 ref가 실제로는 LogProps 컴포넌트를 가리키게 된다는 것이다.
import FancyButton from './FancyButton'
const ref = React.createRef()
// 이 FancyButton 컴포넌트는 LogProps HOC에서 import 했던 컴포넌트다.
// render 결과물은 같지만, ref는 FancyButton 대신 LogProps를 가리킬 것이다.
// 이 뜻은, ref.current.focus() 를 호출하지 못한다는 뜻이다.
<FancyButton
label="Click Me"
handleClick={handleClick}
ref={ref}
>하지만, 우리는 React.forwardRef API를 이용해서 inner FancyButton 컴포넌트에 ref를 전달할 수 있다. React.forwardRef 는 render functions에 props와 ref를 사용할 수 있게 하고 React node를 return 한다.
function logProps(Component){
class LogProps extends Component {
render(){
const { forwaredRef, ...rest} = this.props;
return <Component ref={forwardedRef} { ...rest}>
}
}
return React.forwardRef((props, ref) => { // ref는 React.forwardRef에 의해 전달되는 param이다. LogProps의 일반 prop 처럼 LogProps에 전달가능하다. ex. forwardedRef
return <LogProps {...props} forwardedRef={ref}>
})
}transaction이란 1개 이상의 문서에 대해 읽기 및 쓰기 작업의 집합이다. 각 트랜잭션나 쓰기 batch 에서 쓰기 작업을 수행할 수 있는 최대 문서 수는 500개이다.
트랜잭션은 한 필드의 값을 현재 값 또는 다른 필드의 값에 따라 업데이트 하려는 경우에 유용하다.
트랜잭션은 려러개의 get() 작업과 이어서 수행되는 set(), update() 등의 여러 쓰기 작업으로 구성된다. 동시 수정의 경우 firestore에서는 전체 트랜잭션을 다시 실행한다. 예를 들어 한 트랜잭션에서 문서를 읽고 다른 클라이언트가 해당 문서를 수정하는 경우 Cloud Firestore에서는 해당 트랜잭션을 다시 시도한다. 이 기능을 통해 트랜잭션이 일관된 최신 데이터로 실행된다.
트랜잭션은 쓰기를 부분적으로 적용하지 않는다. 모든 쓰기는 트랜잭션을 성공적으로 마칠 때 실행된다.