[오즈의 제작소 NINJA] 21/05/28
switch case lexical scope
프로덕트 수정
프로덕트의 텍스트 내용을 수정하면
dispatch({ type: 'CHANGE_TEXT_MODAL_VALUE', payload: { newValue: tempCurrentProduct } });
의 액션을 수행.
currentProduct
의 내용을 수정하고, reducer
로 보내서
reducer
에서 products
을 순회하며 currentProduct
와 일치하는 product
를 바꿈
상태 저장.
useEffect 이슈
/factory/1
에서 안보이는 이슈
useEffect(() => {
if (data && categoryData) {
const hashtags: any = {};
const allKinds: any = {};
const { category } = categoryData;
Object.keys(category).forEach(item =>
category[item].Kinds.forEach((kind: any) => {
allKinds[kind.name] = kind.id;
hashtags[kind.name] = kind.Hashtags;
})
);
const { groupedProducts, items, kinds } = makeGroup(data.productOfFactory);
dispatch({
type: 'INIT_TABLE',
payload: {
allProducts: groupedProducts,
allItems: items,
allKinds: kinds,
// 내가 만든거 밑에
allHashtags: hashtags,
allKindsById: allKinds,
},
});
}
}, [data, categoryData]);
Context API Reducer
action
이 오면 첫 라인부터 쭉 순서대로 수행. 잊지말자 헷갈리면안된다.
import { TableActionType, TableStateType } from '@/contexts/FactoryTableContext/types';
export function tableReducer(state: TableStateType, action: TableActionType): TableStateType {
let currentItem: string;
let currentKind: string;
let items: Array<string>;
let kinds: Array<string>;
let products: any;
let currentProducts: any;
switch (action.type) {
case 'OPEN_MODAL':
return {
...state,
modal: { ...state.modal, ...action.payload },
};
/* products(배열)=>currentProducts(객체)로 변경하였음. */
case 'INIT_TABLE':
[currentItem] = Object.keys(action.payload.allProducts); // first element of items
kinds = Object.keys(action.payload.allProducts[currentItem]);
[currentKind] = kinds; // first element of kinds
currentProducts = {};
action.payload.allProducts[currentItem][currentKind].forEach((product: any) => {
currentProducts[`${product.id}`] = product;
});
return {
...state,
factory: {
...state.factory,
...action.payload,
},
table: {
...state.table,
kinds,
currentItem,
currentKind,
allHashtags: { ...state.table.allHashtags, ...action.payload.allHashtags },
allKindsById: { ...state.table.allKindsById, ...action.payload.allKindsById },
currentProducts,
},
};
case 'CHANGE_CURRENT_ITEM':
kinds = Object.keys(state.factory.allProducts[action.payload.currentItem]);
[currentKind] = kinds; // first element of kinds
console.log(currentProducts);
currentProducts = {};
state.factory.allProducts[action.payload.currentItem][currentKind].forEach((product: any) => {
currentProducts[`${product.id}`] = product;
});
return {
...state,
table: {
...state.table,
...action.payload,
kinds,
currentKind,
currentProducts,
},
};
case 'CHANGE_CURRENT_KIND':
currentProducts = {};
state.factory.allProducts[state.table.currentItem][action.payload.currentKind].forEach(
(product: any) => {
currentProducts[`${product.id}`] = product;
}
);
return {
...state,
table: {
...state.table,
...action.payload,
currentProducts,
},
};
/* 로우 추가버튼. 상품 테이블에 로우하나 추가된다. */
case 'ADD_EMPTY_PRODUCT':
return {
...state,
table: {
...state.table,
currentProducts: {
...state.table.currentProducts,
[action.payload.newValue.id]: action.payload.newValue,
},
isModifed: { ...state.table.isModifed, [action.payload.newValue.id]: true },
},
};
/* 프로덕트 셀(텍스트 셀,이미지 셀,해시태그 셀) 데이터 변경되면 반영함 */
case 'CHANGE_PRODUCT_CELL':
return {
...state,
table: {
...state.table,
currentProducts: {
...state.table.currentProducts,
[action.payload.newValue.id]: action.payload.newValue,
},
isModifed: { ...state.table.isModifed, [action.payload.newValue.id]: true },
},
};
/* 수정 클릭하면 클릭한 상품의 수정 버튼 사라져야함 */
/* 셀 데이터들은 이미 CHANGE PRODUCT CELL 액션으로 수정되어있음 */
case 'UPDATE_PRODUCT':
return {
...state,
table: {
...state.table,
isModifed: {
[action.payload.productId]: false,
},
},
};
/* 삭제 클릭하면 클릭한 상품 없어짐 */
case 'DELETE_PRODUCT':
currentProducts = state.table.currentProducts;
delete currentProducts[action.payload.productId];
return {
...state,
table: {
...state.table,
currentProducts: {
...currentProducts,
},
},
};
/* 클릭하면 상태가 가리키는 현재 상품 바뀜 */
case 'CHANGE_CURRENT_PRODUCT':
return {
...state,
modal: {
...state.modal,
currentProduct: action.payload.currentProduct,
},
};
case 'ADD_KIND':
items = Object.keys(action.payload.selectKind);
kinds = Object.keys(action.payload.selectKind)
.map((item: string) => action.payload.selectKind[item].map((kind: string) => kind))
.reduce((acc, cur) => acc.concat(cur), []);
products = {};
Object.keys(action.payload.selectKind).forEach((item: string) => {
products[item] = {};
action.payload.selectKind[item].forEach((kind: string) => {
if (
state.factory.allItems.some((ai: string) => ai === item) &&
state.factory.allKinds.some((ak: string) => ak === kind)
) {
products[item][kind] = state.factory.allProducts[item][kind];
} else {
products[item][kind] = [];
}
});
});
return {
...state,
factory: {
...state.factory,
allItems: items,
allKinds: kinds,
allProducts: products,
},
table: {
...state.table,
currentItem: action.payload.currentItem,
kinds: products[action.payload.currentItem]
? Object.keys(products[action.payload.currentItem])
: [],
},
};
default:
throw new Error('없는 액션');
}
}
div onClick Function Error
<div key={key} data-id={`${product.id}`} onClick={onClickRow} role="button" tabIndex={index}>
<div key={key} data-id={`${product.id}`} onClick={onClickRow} role="button" tabIndex={index}>
자꾸 롤을 추가하라는 에러가 발생함.
role
에 명시한 후 tabIndex
에 index
값을 넣어주자
tabIndex
탭같은걸로 포커스를 지정할 수 있다. 레퍼런스 볼것
as Type
const onClickCell = ({ e, type }: TOnClickCellProps) => {
// type을 TOnClickCellProps로 정의하여 string => 특정 타입으로 제한할 수 있다.
const columnString = (e.currentTarget as HTMLDivElement).dataset.column as ColumnStringType;
// ColumnString을 string => 특정 값만 가지도록 제한해야
const { offsetTop: top, offsetLeft: left } = e.currentTarget as HTMLDivElement;
dispatch({
type: 'OPEN_MODAL',
payload: {
type,
// 여기다 대입할 수 있다.
position: { top, left },
columnString: columnString || '',
// 여기다 대입할 수 있다.
},
});
setIsActive(true);
};
Reference
Author And Source
이 문제에 관하여([오즈의 제작소 NINJA] 21/05/28), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@rat8397/오즈의-제작소-NINJA-210528
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
const onClickCell = ({ e, type }: TOnClickCellProps) => {
// type을 TOnClickCellProps로 정의하여 string => 특정 타입으로 제한할 수 있다.
const columnString = (e.currentTarget as HTMLDivElement).dataset.column as ColumnStringType;
// ColumnString을 string => 특정 값만 가지도록 제한해야
const { offsetTop: top, offsetLeft: left } = e.currentTarget as HTMLDivElement;
dispatch({
type: 'OPEN_MODAL',
payload: {
type,
// 여기다 대입할 수 있다.
position: { top, left },
columnString: columnString || '',
// 여기다 대입할 수 있다.
},
});
setIsActive(true);
};
Author And Source
이 문제에 관하여([오즈의 제작소 NINJA] 21/05/28), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@rat8397/오즈의-제작소-NINJA-210528저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)