export default function Page() {
return (
<Section>
<Heading level={1}>Title</Heading>
<Section>
<Heading level={2}>Heading</Heading>
<Heading level={2}>Heading</Heading>
<Heading level={2}>Heading</Heading>
<Section>
<Heading level={3}>Sub-heading</Heading>
<Heading level={3}>Sub-heading</Heading>
<Heading level={3}>Sub-heading</Heading>
<Section>
<Heading level={4}>Sub-sub-heading</Heading>
<Heading level={4}>Sub-sub-heading</Heading>
<Heading level={4}>Sub-sub-heading</Heading>
</Section>
</Section>
</Section>
</Section>
);
}
export default function Section({ children }) {
return (
<section className="section">
{children}
</section>
);
}
export default function Heading({ level, children }){
switch (level) {
case 1:
return <h1>{children}</h1>;
case 2:
return <h2>{children}</h2>;
case 3:
return <h3>{children}</h3>;
case 4:
return <h4>{children}</h4>;
case 5:
return <h5>{children}</h5>;
case 6:
return <h6>{children}</h6>;
default:
throw Error('Unknown level: ' + level);
}}
<Heading>
component know the level of its closest <Section>?
That would require some way for a child to “ask” for data from somewhere above in the tree.<Heading>
컴포넌트는 어떻게 가장 가까운 <Section>
의 레벨을 알 수 있을까요? 이는 어떤 방식으로 자식이 트리 상단의 데이터를 '요청'할 수 있는 방법을 필요로 합니다<Section>
<Heading level={3}>About</Heading>
<Heading level={3}>Photos</Heading>
<Heading level={3}>Videos</Heading>
</Section>
<Section level={3}>
<Heading>About</Heading>
<Heading>Photos</Heading>
<Heading>Videos</Heading>
</Section>
This tells React: “if any component inside this <Section>
asks for LevelContext, give them this level.” The component will use the value of the nearest
상위 컴포넌트 예제
import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
<section className="section">
<LevelContext.Provider value={level}>
{children}
</LevelContext.Provider>
</section>
);
}
import { createContext } from 'react';
export const LevelContext = createContext(1);
상위 컴포넌트에서
<LevelContext.Provider value={level}>
형태로 데이터를 보내준다.
하위 컴포넌트에서
const level = useContext(LevelContext);
형태로 사용한다.
완성본은 다음과 같다.
import {createContext, useContext} from "react";
const LevelContext = createContext(1);
export default function Page() {
return (
<Section level={1}>
<Heading>Title</Heading>
<Section level={2}>
<Heading>Heading</Heading>
<Heading>Heading</Heading>
<Heading>Heading</Heading>
<Section level={3}>
<Heading>Sub-heading</Heading>
<Heading>Sub-heading</Heading>
<Heading>Sub-heading</Heading>
<Section level={4}>
<Heading>Sub-sub-heading</Heading>
<Heading>Sub-sub-heading</Heading>
<Heading>Sub-sub-heading</Heading>
</Section>
</Section>
</Section>
</Section>
);
}
function Section({ level,children }) {
return (
<section className="section">
<LevelContext.Provider value={level}>
{children}
</LevelContext.Provider>
</section>
);
}
function Heading({ children }){
const level = useContext(LevelContext);
switch (level) {
case 1:
return <h1>{children}</h1>;
case 2:
return <h2>{children}</h2>;
case 3:
return <h3>{children}</h3>;
case 4:
return <h4>{children}</h4>;
case 5:
return <h5>{children}</h5>;
case 6:
return <h6>{children}</h6>;
default:
throw Error('Unknown level: ' + level);
}
}
<Layout posts={posts} />
. Instead, make Layout take children as a prop, and render <Layout><Posts posts={posts} /></Layout>
. This reduces the number of layers between the component specifying the data and the one that needs it.store.dispatch()
and pass in an action object. The store will run its reducer
function and save the new state value inside.
const counterReducer = (state= 0, action) => {
switch (action.type) {
case "INCREMENT":
return state + 1;
case "DECREMENT":
return state - 1;
case "RESET":
return (state = 0);
default:
return state;
}
}
export default counterReducer;
store.dispatch(action)
, the storeimport {useSelector, useDispatch } from 'react-redux';
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector(state => state);
const incrementHandler = () => {
dispatch({type: 'INCREMENT'});
}
const decrementHandler = () => {
dispatch({type: 'DECREMENT'});
}
const resetHandler = () => {
dispatch({type: 'RESET'});
}
return (
<div>
<h2>Redux Counter</h2>
<div>{counter}</div>
<button onClick={incrementHandler}>Increment</button>
<button onClick={decrementHandler}>Decrement</button>
<button onClick={resetHandler}>Reset</button>
</div>
);
};
export default Counter;
import {createStore} from "redux";
import counterReducer from "../components/counterReducer";
const store = createStore(counterReducer);
export default store;
import React from 'react';
import Counter from './components/Counter';
function App() {
return (
<Counter />
);
}
export default App;
<Provider>
component makes the Redux store available to any nested components that need to access the Redux store.import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import store from './store/index';
import {Provider} from "react-redux";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
import { useRef } from 'react';
const ref = useRef(0);
{
current: 0 // The value you passed to useRef
}
ref.current
import { useRef } from 'react';
export default function Counter() {
let ref = useRef(0);
function handleClick() {
ref.current = ref.current + 1;
alert('You clicked ' + ref.current + ' times!');
}
return (
<button onClick={handleClick}>
Click me!
</button>
);
}
useeffect 사용하지 않고도 바로 반영이 가능하구나