src/App.js
export let StockContext = createContext() // 1.컨텍스트 만들고
<Route path='/detail/:id' element={
<StockContext.Provider value={{stock}}>
<Detail shrits={shrits} />
</stockContext.Provider>
}/>
src/component/Detail.js
import { StockContext } from '../App'
function Detail(props) {
let {stock} = useContext(StockContext);
이렇게 해서 전역변수처럼 쓸 수 있다.
src/component/Cart.js
npm install @reduxjs/toolkit react-redux
src/index.js
import store from './store.js'
import { Provider } from 'react';
root.render(
<Provider store = {store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
src/component/Store.js
// 앞으로 데이터들을 담아 둘 저장 공간
import { configureStore, createSlice} from "@reduxjs/toolkit"
let user = createSlice({
name : 'user',
initialState : 'Lee'
})
let stock = createSlice({
name : 'stock',
initialState : [1,13,20]
})
export default configureStore({
reducer : {
user: user.reducer,
stock : stock.reducer
}
})
src/component/Cart.js
// 사용할 곳
import {useSelector} from "react-redux";
function Cart() {
let state = useSelector((state)=>{return state});
console.log(state);
결과 :
store.js
import { configureStore, createSlice } from "@reduxjs/toolkit"
let user = createSlice({
name : 'user',
initialState : 'Lee',
reducers: {
changeName(state) {
//'yuna' + state
return {state.name = 'kang'}
},
userNameChange(state){
// return "string + state
return state.name = 'Lee'
}
increase(state){
state.age += 1
}
}
//state 수정하길 원하는 함수 작성한다.
})
export let { changeName , userNameChange, increase} = user.actions
Cart.js
import { changeName } from "../store";
let state = useSelector((state) => state )
let dispatch = useDispatch();
p415 // 단, 18버전 툴킷? 이라는 새로운 방법을 고려한다.
WILL : 작업 전
Did : 작업 작동 후
마운트 : 페이지에 컴포넌트가 나타남
마운트 순서 : constructor->getDerivedStateFromProps->render->componentDidMount
constructor: 클래스 생성자 메서드
getDerivedStateFromProps: props에 있는 값을 state에 넣을 때 사용
render : 우리가 준비한 UI를 렌더링
componentDidMount : 컴포넌트가 웹 브라우저 상에 나타난 후 호출
업데이트 : 컴포넌트 정보를 업데이트
props,state가 바뀔때
부모 컴포넌트가 리렌더링될 때
this.forceUpdate로 강제 렌더링을 트리거할 때
언마운트 : 페이지에서 컴포넌트가 사라짐
src/LifeCycleSample.js
BEFORE 렌더링
//부모로부터 받은 color 값을 state에 동기화 static getDerivedStateFromProps(nextProps, prevState) { console.log('getDerivedStateFromProps'); if (nextProps.color !== prevState.color) { return { color: nextProps.color }; } return null; }
SET 렌더링
//컴포넌트의 리렌더링을 할지 안할지 결정하는 함수 //여기서는 state.number의 마지막 자리수가 4면 리렌더링을 취소 shouldComponentUpdate(nextProps, nextState) { console.log('shouldComponentUpdate', nextProps, nextState); // 숫자의 마지막 자리가 4면 리렌더링하지 않습니다. return nextState.number % 10 !== 4; }
AFTER 렌더링
//컴포넌트 변화를 DOM에 보여주기 바로 직전에 호출하는 메소드 //여기서는 변화 직전의 색상속성을 snapshot값으로 반환하여 componentDidUpdate에서 조회할 수 있게 한다 getSnapshotBeforeUpdate(prevProps, prevState) { console.log('getSnapshotBeforeUpdate'); if (prevProps.color !== this.props.color) { return this.myRef.style.color; } return null; } //컴포넌트의 업데이트 작업이 끝난 후 호출되는 함수, //여기서는 업데이트 직전의 색상을 저장한 스냅샷을 콘솔로그에 보여주고있다. componentDidUpdate(prevProps, prevState, snapshot) { //변화직전의 속성값을 조회가능 console.log('componentDidUpdate', prevProps, prevState); if (snapshot) { console.log('업데이트되기 직전 색상: ', snapshot); } }
사용법
src/ErrorBoundary.js
import React, { Component } from 'react';
class ErrorBoundary extends Component {
state = {
error: false
};
componentDidCatch(error, info) {
this.setState({
error: true
});
console.log({ error, info });
}
render() {
if (this.state.error) return <div>에러가 발생했습니다!</div>;
return this.props.children;
}
}
export default ErrorBoundary;
src/App.js
//에러가 날 법한 곳을 <ErrorBoundary>로 감싸준다
import ErrorBoundary from './ErrorBoundary';
<ErrorBoundary>
<LifeCycleSample color={this.state.color} />
</ErrorBoundary>
결과 : 흰 화면이 아닌 에러발생 문구를 사용자에게 알려준다.
css 클래스가 특정 클래스 내부에 있는 경우에만 스타일을 적용 시킬 수 있다.
예를 들어 .App 안에 들어있는 .logo에 스타일을 적용하고 싶다면 다음과 같이 작성한다
.App .logo{
animation: App-logo-spin infinite 20s linear;
heigh: 40vmin;
}
법적으로 매우 멋진 스타일시트라는 뜻으로, 복잡한 작업을 쉽게, 코드 재활용, 가독성 ---> 유지보수 쉽게
설치
React 프로젝트에 Router 설치 방법
1. 터미널을 킨다.
2. Sass 설치를 희망하는 React프로젝트의 디렉토리로 이동한다.
3. npm install node-sass --save 입력한다.
4. 설치한 React 프로젝트 디렉토리를 열어 package.json 파일에 "dependencies" 중 "node-sass" 이 있는지 확인해 본다.
에러가 있다면 이전 설치 참고해서 nodejs버전과 npm 버전을 체크하고
yarn으로 설치를 추천한다.
https://velog.io/@meat7238/221124
yarn add sass
`SassComponent
.SassComponent {
display: flex;
background: $oc-gray-2;
@include media("<768px") {
background: $oc-gray-9;
}
.box {
background: red; // 일반 CSS 에선 .SassComponent .box 와 마찬가지
cursor: pointer;
transition: all 0.3s ease-in;
&.red {
// .red 클래스가 .box 와 함께 사용 됐을 때
background: $red;
@include square(1);
}
&.orange {
background: $orange;
@include square(2);
}
&.yellow {
background: $yellow;
@include square(3);
}
&.green {
background: $green;
@include square(4);
}
&.blue {
background: $blue;
@include square(5);
}
&.indigo {
background: $indigo;
@include square(6);
}
&.violet {
background: $violet;
@include square(7);
}
&:hover {
// .box 에 마우스 올렸을 때
background: black;
}
}
}
utils.scss
@import '~include-media/dist/include-media';
@import '~open-color/open-color';
// 변수 사용하기
$red: #fa5252;
$orange: #fd7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo: #5c7cfa;
$violet: #7950f2;
// 믹스인 만들기 (재사용되는 스타일 블록을 함수처럼 사용 할 수 있음)
@mixin square($size) {
$calculated: 32px * $size;
width: $calculated;
height: $calculated;
}
p236
자바스크립트 하나에 스타일까지 작성할 수 있는 이점이 있다.
설치
yarn add styled-componets
npm install styled-components
src/StyledComponents.js
import React from 'react';
import styled, { css } from 'styled-components';
const sizes = {
desktop: 1024,
tablet: 768
};
// 위에있는 size 객체에 따라 자동으로 media 쿼리 함수를 만들어줍니다.
// 참고: https://www.styled-components.com/docs/advanced#media-templates
const media = Object.keys(sizes).reduce((acc, label) => {
acc[label] = (...args) => css`
@media (max-width: ${sizes[label] / 16}em) {
${css(...args)};
}
`;
return acc;
}, {});
const Box = styled.div`
/* props 로 넣어준 값을 직접 전달해줄 수 있습니다. */
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
width: 1024px;
margin: 0 auto;
${media.desktop`width: 768px;`}
${media.tablet`width: 100%;`};
`;
const Button = styled.button`
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;
/* & 문자를 사용하여 Sass 처럼 자기 자신 선택 가능 */
&:hover {
background: rgba(255, 255, 255, 0.9);
}
/* 다음 코드는 inverted 값이 true 일 때 특정 스타일을 부여해줍니다. */
${props =>
props.inverted &&
css`
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`};
& + button {
margin-left: 1rem;
}
`;
const StyledComponent = () => (
<Box color="black">
<Button>안녕하세요</Button>
<Button inverted={true}>테두리만</Button>
</Box>
);
export default StyledComponent;
src/App.js
import React, { Component } from "react";
import StyledComponent from "./StyledComponent";
class App extends Component {
render() {
return (
<div>
<StyledComponent />
</div>
);
}
}
export default App;
결과 :
!! vsCode에 vscode-styled-components 추가 설치해두면 js안에서도 css 색상이 정상적으로 입력된다
백틱 사의의 객체나 함수는 일반적으로 형태를 잃어버린다
`hello ${{foo: 'bar}} ${() => 'world'}!`
결과> "hello object Object => 'world'!"
하지만 Tagged 템플릿 리터럴을 쓰면 값이 출력된다.
import styled from 'styled-components';
const MyComponent = styled.div`
font-size: 2rem;
`;
const MyInput = styled('input')`
background: gray;
`
const StyledLink = styled(Link)`
color: blue;
`
결과>div로 이루어진 리액트 컴포넌트가 생성된다. 나중에 Hello처럼 쓸 수 있다.
input이나 button에 스타일링을 하고 싶다면 styled.button 등으로 넣으면 된다.
유동적이거나 특정 컴포넌트의 경우에도 위와 같은 형태로 구현할 수 있다.
스타일컴포넌트의 스타일에 변수로 넣어준 값을 직접 전달 해 줄 수 있다
const Box = styled.div`
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
`
=>props를 조회해서 props.color의 값을 사용하게 함