Algorithm
function solution(clothes) {
let answer =1;
let clothe = {}
clothes.forEach(v=>{
clothe[v[1]] = clothe[v[1]]?clothe[v[1]]+1:1
})
let arr = Object.values(clothe)
if(arr.length===1) return clothes.length
let r = arr
for(let i=0; i<arr.length; i++) {
answer *= arr[i]+1
}
return answer-1;
}
해시를 사용한 문제 풀이이다. 알고리즘 레벨이 높아지면서 점점 수학적 지식이 필요해지는 거 같다
function solution(clothes) {
return Object.values(clothes.reduce((obj, t)=> {
obj[t[1]] = obj[t[1]] ? obj[t[1]] + 1 : 1;
return obj;
} , {})).reduce((a,b)=> a*(b+1), 1)-1;
}
다른 사람 풀이도 문제 접근법은 동일하며 배열함수를 활용한 방법이 다른데
reduce
반복문을 통해 reduce
의 처음 값이 {}
걸 활용하여 해시 데이터로 다루고 Object.values
를 통해 배열화, 이후 다시 reduce
를 활용해 값을 계산한다.
CS
이미 알고 사용하고 있는것도 완벽히 개념적으로 잡고 가보자.
일단 Context API는 리액트에 내장된 기능으로 Props를 사용하지 않아도 특정 값이 필요한 컴포넌트끼리 쉽게 값을 공유할 수 있게 해준다.
주로 프로젝트에서 전역 상태를 관리할 때 많이 사용한다.
하지만 reduce에서의 강력한 미들웨어 기능이 없는 것은 있다.
리덕스에서의 store와 같은 하나의 Context 객체가 필요하다
import React, {createContext} from 'react';
const MyContext = createContext();
export default MyContext;
위 처럼 context 객체를 생성하고 export 하였다면 Provider를 생성할 수 있다.
Provider는 context의 뿌리라고 할 수 있는데 필요한 모든 것을 담고 있고, Consumer로 wrpping된 컴포넌트는 Provider에 접근 할 수 있다.
Provider를 리덕스처럼 자식 컴포넌트들을 wrapping한다
여기서 차이점이라고 한다면 리덕스는 하나의 store를 사용하는 것이 기본적인 룰인데 반해, Context API는 다수의 Context를 만들 수 있다
export const MarketContext = createContext();
export const MarketContextProvider = ({ children }) => {...
return (
<MarketContext.Provider
value={{
items: initialState.items,
cart: { cartState, cartDispatch },
check: { checkState, checkDispatch },
}}
>
{children}
</MarketContext.Provider>
);
};
리액트의 빌트인 훅인 useContext를 통하여 컴포넌트는 간단하게 자신을 wrapping하고 있는 Provider의 value에 접근 가능하다
const { items, cart, check } = useContext(MarketContext);
요런식으로 말이다
Context API는 렌더링에 있어 다소 아쉬운 점이 있다
Provider의 value prop에 잇는 state와 dispatch가 변할 때마다, Provider를 구독하고 있는 모든 컴포넌트들이 리렌더링 된다
useMemo를 통해 Provider의 value props를 메모이제이션 하거나
독립적인 context를 만들어주는 방법이 있다
이번 프로젝트에서 Next.js를 사용하다 보니 Context API를 사용했는데 여기서 생긴 렌더링 문제가 있긴 했다
Context는 useReducer hook과 함께 사용한다면 더욱 직관적이며 코드의 양도 줄어든다.
switch...case
그거 맞다
리액트를 처음 들어가보면 분명 html코드인데 맞나 싶은 것들이 눈에 띄게 보이는데 바로 살펴보자
function App(){
return(
<h1>test</h1>
<p>test...</p>
)
}
이처럼 되어 있다면 해당 요소를 감싸는 부모 요소가 존재해야한다. 에러가 발생함
function App(){
return(
<div>
<h1>test</h1>
<p>test...</p>
</div>
)
}
여기서 <></>
처럼 빈 요소로 감싸도 동작하긴 한다.
일단 이렇게 감싸는 이유는, 리액트가 사용하는 Virtual DOM방식에서는 컴포넌트 변화를 감지할 때 효율적으로 비교하기 위해 컴포넌트 내부는 하나의 DOM트리 구조로 이루어져야 한다는 규칙이 있기 때문이다
{name}
과 같이 넣어서 렌더링 가능하다function App(){
const name = "myApp"
return(
<div>
<h1>test</h1>
<p>{name}</p>
</div>
)
}
function App(){
const bool = true
return(
<div>
{bool?
(<p>참</p>):
(<p>거짓</p>)
}
</div>
)
}
function App() {
const name = undefined;
return name;
}
이는 OR연산자를 사용해 방지할 수 있으며 JSX내부에서 undefined를 렌더링 하는 것은 에러가 나지 않는다
function App() {
const name = undefined;
return name || "값이 undefined";
}
//또는
function App() {
const name = undefined;
return (
<div>{name}</div>
)
}
background-color -> backgroundColor
//HTML
<div class="classEx1">
</div>
// JSX
<div className="classEx1">
</div>
이는 엄연히 HTML처럼 보이지만 HTML이 아니기 때문이다
HTML등에서 input태그 등은 별도로 닫지 않아도 괜찮았지만, JSX에서는 반드시 닫아주는 태그를 작성해야 한다
<input></input> // 혹은 다음과 같이 self-closing 태그로 작성해도 무방 <input />
JSX내에서 주석을 작성할 때에는 {/.../}와 같은 형식으로 작성한다
시작태그를 여러줄로 작성 시, 그 내부에서 // 를 사용하여 주석을 작성할 수도 있다
<div
className="classEx1" // 주석 작성 가능
>
</div>
Refrence