๐ป
33์ผ์ฐจ
Part 10. React ๋ก ์ผํ๋ชฐ ๋ง๋ค๊ธฐ (React ๊ธฐ๋ณธ)
Ch 2. React Component
Ch 2. React Component
๐ React Component ๋ง๋๋ ๋ฒ
// Class Component
// ์ ์
class ClassComponent extends React.Component {
render() {
return <div>Hello</div>;
}
}
// ์ฌ์ฉ
ReactDOM.render(<ClassComponent />, document.querySelector("#root"));
// Function Component 1
// ์ ์
function FunctionComponent() {
return <div>Hello</div>;
}
// ์ฌ์ฉ
ReactDOM.render(<FunctionComponent />, document.querySelector("#root"));
// Function Component 2
// ์ ์
const FunctionComponent = () => <div>Hello</div>;
// ์ฌ์ฉ
ReactDOM.render(<FunctionComponent />, document.querySelector("#root"));
๐ React.createElement ๋ก ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ
React.createElement(
type, // ํ๊ทธ ์ด๋ฆ ๋ฌธ์์ด | ๋ฆฌ์กํธ ์ปดํฌ๋ํธ | React.Fragment
[props], // ๋ฆฌ์กํธ ์ปดํฌ๋ํธ์ ๋ฃ์ด์ฃผ๋ ๋ฐ์ดํฐ ๊ฐ์ฒด
[...children] // ์์์ผ๋ก ๋ฃ์ด์ฃผ๋ ์์๋ค
);
// 1. ํ๊ทธ ์ด๋ฆ ๋ฌธ์์ด type
// <h1>type ์ด "ํ๊ทธ ์ด๋ฆ ๋ฌธ์์ด" ์
๋๋ค.</h1>;
ReactDOM.render(
React.createElement("h1", null, `type ์ด "ํ๊ทธ ์ด๋ฆ ๋ฌธ์์ด" ์
๋๋ค.`),
document.querySelector("#root")
);
// 2. ๋ฆฌ์กํธ ์ปดํฌ๋ํธ type
const Component = () => {
return React.createElement(
"p",
null,
`type ์ด "React ์ปดํฌ๋ํธ" ์
๋๋ค.`
);
};
// <Component /> => <p>`type ์ด "React ์ปดํฌ๋ํธ" ์
๋๋ค.`</p>
ReactDOM.render(
React.createElement(Component, null, null),
document.querySelector("#root")
);
// 3. React.Fragment => ์์๋ฅผ ์ฌ๋ฌ๊ฐ ๋ฃ์ ์ ์๋ค.
ReactDOM.render(
React.createElement(
React.Fragment,
null,
`type ์ด "React Fragment" ์
๋๋ค.`,
`type ์ด "React Fragment" ์
๋๋ค.`,
`type ์ด "React Fragment" ์
๋๋ค.`
),
document.querySelector("#root")
);
// 4. ๋ณต์กํ ๋ฆฌ์กํธ ์๋ฆฌ๋จผํธ ๋ชจ์
// <div>
// <div>
// <h1>์ฃผ์ </h1>
// <ul>
// <li>React</li>
// <li>Vue</li>
// </ul>
// </div>
// </div>;
ReactDOM.render(
React.createElement(
"div",
null,
React.createElement(
"div",
null,
React.createElement("h1", null, "์ฃผ์ "),
React.createElement(
"ul",
null,
React.createElement("li", null, "React"),
React.createElement("li", null, "Vue")
)
)
),
document.querySelector("#root")
);
๐ JSX
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
// ์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ด๋ค ์ฝ๋๋ฅผ => ์์ํ๊ฒ ์คํํ ์ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ
// babel
const title = "์ฃผ์ ";
ReactDOM.render(
<div a="a">
<div>
<h1>{title}</h1>
<ul>
<li>React</li>
<li>Vue</li>
</ul>
</div>
</div>,
document.querySelector("#root")
);
๐ Props ์ State
// {message: '์๋
ํ์ธ์!'}
function Component(props) {
return (
<div>
<h1>{props.message} ์ด๊ฒ์ ํจ์๋ก ๋ง๋ ์ปดํฌ๋ํธ ์
๋๋ค.</h1>
</div>
);
}
Component.defaultProps = {
message: "๊ธฐ๋ณธ๊ฐ",
};
ReactDOM.render(
<Component message="๊ธฐ๋ณธ๊ฐ ์๋" />,
document.querySelector("#root")
);
class Component extends React.Component {
// state = {
// count: 0,
// };
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
render() {
return (
<div>
<h1>
{this.props.message} ์ด๊ฒ์ ํด๋์ค๋ก ๋ง๋ ์ปดํฌ๋ํธ ์
๋๋ค.
</h1>
<p>{this.state.count}</p>
</div>
);
}
componentDidMount() {
setTimeout(() => {
// this.setState({
// count: this.state.count + 1,
// });
this.setState((previousState) => {
const newState = {
count: previousState.count + 1,
};
return newState;
});
}, 1000);
}
static defaultProps = {
message: "๊ธฐ๋ณธ๊ฐ2",
};
}
ReactDOM.render(
<Component message="๊ธฐ๋ณธ๊ฐ ์๋" />,
document.querySelector("#root")
);
๐ Event Handling
class Component extends React.Component {
state = {
count: 0,
};
// constructor(props) {
// super(props);
// this.click = this.click.bind(this);
// }
render() {
return (
<div>
<p>{this.state.count}</p>
<button onClick={this.click}>ํด๋ฆญ</button>
</div>
);
}
click = () => {
console.log("clicked");
this.setState((state) => ({
...state,
count: state.count + 1,
}));
};
}
ReactDOM.render(<Component />, document.querySelector("#root"));
๐ Component Lifecycle
(v16.3 ์ด์ )
class App extends React.Component {
state = {
age: 39,
};
interval = null;
constructor(props) {
super(props);
console.log("constructor", props);
}
render() {
console.log("render");
return (
<div>
<h2>
Hello {this.props.name} - {this.state.age}
</h2>
</div>
);
}
componentWillMount() {
console.log("componentWillMount");
}
componentDidMount() {
console.log("componentDidMount");
this.interval = setInterval(() => {
// console.log("setInterval");
this.setState((state) => ({ ...state, age: state.age + 1 }));
}, 1000);
}
componentWillReceiveProps(nextProps) {
console.log("componentWillReceiveProps", nextProps);
}
shouldComponentUpdate(nextProps, nextState) {
console.log("shouldComponentUpdate", nextProps, nextState);
return true; // โญ false or true
}
componentWillUpdate(nextProps, nextState) {
console.log("componentWillUpdate", nextProps, nextState);
}
componentDidUpdate(prevProps, prevState) {
console.log("componentDidUpdate", prevProps, prevState);
}
componentWillUnmount() {
clearInterval(this.interval);
}
}
ReactDOM.render(<App name="Mark" />, document.querySelector("#root"));
(v16.3)
let i = 0;
class App extends React.Component {
state = {
list: [],
};
render() {
return (
<div id="list" style={{ height: 100, overflow: "scroll" }}>
{this.state.list.map((i) => {
return <div>{i}</div>;
})}
</div>
);
}
componentDidMount() {
setInterval(() => {
this.setState((state) => ({ list: [...state.list, i++] }));
}, 1000);
}
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevState.list.length === this.state.list.length) return null;
const list = document.querySelector("#list");
return list.scrollHeight - list.scrollTop;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(snapshot);
if (snapshot === null) return;
const list = document.querySelector("#list");
list.scrollTop = list.scrollHeight - snapshot;
}
}
ReactDOM.render(<App name="Mark" />, document.querySelector("#root"));
๐ Component ์๋ฌ ์บ์น - componentDidCatch
https://reactjs.org/docs/error-boundaries.html
class App extends React.Component {
state = {
hasError: false,
};
render() {
if (this.state.hasError) {
return <div>์์์น ๋ชปํ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.</div>;
}
return <WebService />;
}
componentDidCatch(error, info) {
this.setState({ hasError: true });
}
}
ReactDOM.render(<App name="Mark" />, document.querySelector("#root"));