[오즈의 제작소 NINJA] 21/05/26

33146 단어 projectproject

react-query

공부하기

context API

셋팅하기

기본 개념

// FactoryTable Component

// Context를 만드는 코드
export const TableContext = createContext({ data: '123' });


const FactoryTable = () => (
  // Context를 하위 컴포넌트들에 뿌려주는 Provider 컴포넌트
  <TableContext.Provider value={{ data: '1234' }}>
    
    <Wrapper>
      <CategoryListWrapper>
        <CategoryList category={category} />
      </CategoryListWrapper>
      <TableWrapper>
        <KindsTableWrapper>
          <KindsTable kinds={Kinds} />
        </KindsTableWrapper>
        <FactoryItemsTable />
      </TableWrapper>
    </Wrapper>

  </TableContext.Provider>
);

TableContext.Provider의 내부를 보면 children으로 하위 컴포넌트들을 받고, Provider컴포넌트에서 받는 밸류로 로직 정해서 내보내주지 않을까 생각.

다음과 같이 사용한다.

const CategoryList: React.FC<ICategoryListProps> = ({ category }) => {
  
  // useContext 훅으로 Context 넣어주면 그 Context가 갖고 있는 스테이트 리턴함.
  const context = useContext(TableContext);
  console.log(context);
  const [isFocus, setIsFocus] = useState<string | null>('');
  const onClick = (e: React.MouseEvent<HTMLElement>) => {
    setIsFocus((e.target as HTMLElement).textContent);
  };
  return (
    <Wrapper onClick={onClick}>
      {category.map(item => (
        <Item focus={isFocus === item.name} key={item.id}>
          {item.name}
        </Item>
      ))}
    </Wrapper>
  );
};

React Router

//App.tsx
 <Switch>
            <Route path={routes.home} exact>
              Hello
            </Route>
            <Route path={routes.factoryList} exact component={FactoryListPage} />
              // exact가 빠져있는 경우
            <Route path={routes.factoryDetail} component={FactoryDetailPage} /> 
            <Route path={routes.factoryEdit} exact component={FactoryEditPage} />
              
              
              
            <Route path={routes.factoryRepresentEdit} exact component={FactoryRepresentEditPage} />
            <Route>NotFound</Route>
          </Switch>

routes.factoryDetail
routes.factoryEdit
의 라우터가 routes.factoryDetail로 올 수 있다.

/:id/123 | /:id/123/repe 같은 라우터 들이 /:id로 올 수 있음

그렇기에 다음과 같이 exact속성을 부여해야한다.


            <Route path={routes.factoryDetail} exact component={FactoryDetailPage} />
          

interface vs type

interface 는 객체밖에 안돼

import React, { createContext, Dispatch, useReducer } from 'react';

interface ITableAction {
  type: 'CREATE' | 'TOGGLE';
  payload: string | number | undefined;
}
interface ITableState {
  // 품목 객체
  // 품목 객체 안에 종류 객체
  // 종류 객체 안에는 상품 배열이 있다.
  test: number;
}
interface ITableDispatch {
  dispatch: Dispatch<ITableAction>;
}

const TableContext = createContext<ITableState | undefined>(undefined);
const TableDispatchContext = createContext<ITableDispatch | undefined>(undefined);
const initialTableState = {
  test: 0,
};
function tableReducer(state: ITableState, action: ITableAction): ITableState {
  switch (action.type) {
    case 'CREATE':
      return { test: 1 };
    case 'TOGGLE':
      return { test: 2 };
    default:
      throw new Error('없는 액션');
  }
}

export function TableContextProvider({ children }: { children: React.ReactNode }) {
  const [tableState, dispatch] = useReducer(tableReducer, initialTableState);
  return (
    <TableContext.Provider value={tableState}>
    // TableDispatchContext는 ITableDispatch 인터페이스로 정해진 Context이다. value에 들어가는 값이 ITableDispatch 인터페이스 타입이어야하는데, dispatch 속성을 가진 객체로 인터페이스를 지정했으므로 다음과 같이 넣어주어야함.
      <TableDispatchContext.Provider value={{ dispatch }}>{children}</TableDispatchContext.Provider>
    </TableContext.Provider>
  );
}

value = {dispatch}로 하고싶다면

import React, { createContext, Dispatch, useReducer } from 'react';

interface ITableAction {
  type: 'CREATE' | 'TOGGLE';
  payload: string | number | undefined;
}
interface ITableState {
  // 품목 객체
  // 품목 객체 안에 종류 객체
  // 종류 객체 안에는 상품 배열이 있다.
  test: number;
}
type ITableDispatch = Dispatch<ITableAction>;

const TableContext = createContext<ITableState | undefined>(undefined);
const TableDispatchContext = createContext<ITableDispatch | undefined>(undefined);
const initialTableState = {
  test: 0,
};
function tableReducer(state: ITableState, action: ITableAction): ITableState {
  switch (action.type) {
    case 'CREATE':
      return { test: 1 };
    case 'TOGGLE':
      return { test: 2 };
    default:
      throw new Error('없는 액션');
  }
}

export function TableContextProvider({ children }: { children: React.ReactNode }) {
  const [tableState, dispatch] = useReducer(tableReducer, initialTableState);
  return (
    <TableContext.Provider value={tableState}>
      <TableDispatchContext.Provider value={dispatch}>{children}</TableDispatchContext.Provider>
    </TableContext.Provider>
  );
}

event type

  • onclick으로 이벤트 객체 받는 경우
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    // 여기도 모르니까 any 로 하겠습니다.
    e.preventDefault();
    onSubmit(form);
    setForm({
      name: '',
      description: ''
    }); // 초기화
  };

e객체에다 타입을 명시해주어야함.

// TextCell.tsx
const TextCell: React.FC<ITextCellProps> = ({ content, ...style }) => {
  const onClick = (e: React.MouseEvent<HTMLDivElement>) => {
    console.log('cell click');
    console.log(e.target);
    // 모달 스테이트 만들어서 TextModal isOpen함
  };
  return (
    <Cell {...style} onClick={onClick}>
      <Wrapper>{content}</Wrapper>
    </Cell>
  );
};

주의 : React.MouseEventHandler<HTMLDivElement>와 헷갈려서는 안된다. Handler타입은 함수타입임

허나, 타입을 위 코드처럼 명시하여도 target아래 속성들에는 접근할 수 없다.

어떤 타입을 명시해야 target 아래 속성들에 접근할 수 있을까

디자인 이슈

  • 다음 사진 처럼 벌어지는 이유
  font-size: 11px;

폰트 사이즈가 해시태그 셀 부분만 작았다. 그렇기에 요소의 크기가 다른 셀 크기보다 작게됨. (통일 되지 못하게댐)

폰트사이즈 부분 지우

다음과 같이 생기던 균열이 없어지게됨.

Reference

좋은 웹페이지 즐겨찾기