반응 상태에 대해 알아야 할 것
본고에서 우리는
Class component
에서 Functional component
사이의 상태를 어떻게 사용하는지 이해하고 주의사항을 제시하고자 한다...이게 어떻게 된 일입니까?
특히 React 구성 요소에 상호작용을 추가하기를 원할 수도 있습니다.이러한 상호작용은 UI를 바꿀 수 있다. 이런 상황에서 데이터를 React 상태에 저장하고 그 기능의 표현 방식을 바꿀 수 있다.
props
과 달리 구성 요소는 상태를 변경할 수 있습니다.그러나 상태를 변경할 때 구성 요소를 다시 보여주려면 몇 가지 규칙을 따라야 한다.어디 보자.클래스 구성 요소
네가 지금 알고 있는 것에 들어가기 전에, 예를 들면 갈고리.갈고리가 존재하지 않는 시대였다. 상태 구성 요소를 가진 유일한 방법은 구성 요소 종류를 사용하는 것이다.
Note: It's in the version
16.8.6
ofReact
that hooks has been exposed by the library.
Component class
을 만드는 방법은 class
을 만들고 React.Component
클래스를 확장한 다음 라이프 사이클 메소드에 액세스할 수 있습니다.constructor
componentDidMount
componentDidUpdate
render
(필수) componentWillUnmount
import React from "react";
class MyClassComponent extends React.Component {
render() {
return <p>A simple class component</p>;
}
}
초기화
그런 다음 두 가지 방법으로 상태를 초기화할 수 있습니다.
constructor
class MyClassComponent extends React.Component {
constructor() {
this.state = {
firstName: "Bob",
lastName: "TheSponge",
};
}
render() {
return <p>A simple class component with a state</p>;
}
}
state
class MyClassComponent extends React.Component {
state = {
firstName: "Bob",
lastName: "TheSponge",
};
render() {
return <p>A simple class component with a state</p>;
}
}
Note: You can use both as you wish. It's the same. But constructor will give you the possibility to use
props
to initialize the state.
국가에 들어가다
예상대로 이제
this.state
을 사용하여 주에 액세스할 수 있습니다.class MyClassComponent extends React.Component {
state = {
firstName: "Bob",
lastName: "TheSponge",
};
render() {
return (
<div>
<p>First name: {this.state.firstName}</p>
<p>Last name: {this.state.lastName}</p>
</div>
);
}
}
상태 업데이트
만약
state
이 업데이트된 적이 없다면, 이 데이터를 저장할 상태가 필요하지 않을 수도 있습니다.업데이트하려면 구성 요소 실례
setState
에서 접근 방법 this
의 상태를 찾을 수 있습니다.그리고 너는 이 주의 어떤 일도 바꿀 수 있다.
setState
에 대해 알아야 할 사항useState
의 구성 요소 클래스와 달리 setState
은 업데이트된 데이터를 이전 데이터와 자동으로 결합합니다.class MyClassComponent extends React.Component {
state = {
firstName: "Bob",
lastName: "TheSponge",
};
updateFirstName = () => {
// It will result having a state with
// { firstName: 'New firstName', lastName: 'TheSponge' }
this.setState({ firstName: "New firstName" });
};
render() {
const { firstName, lastName } = this.state;
return (
<div>
<p>First name: {firstName}</p>
<p>Last name: {lastName}</p>
<button
type="button"
onClick={this.updateFirstName}
>
Update firstName
</button>
</div>
);
}
}
Warning: It will not deeply merge. Just shallow stuff. If you need to update a single key of an object store in a state, you will have to update it in function of the previous object stored.
이전 함수의 상태 업데이트
위에서 경고한 바와 같이 당신이 생각하기에
그런 다음
setState
함수의 다른 API를 사용합니다.Yep
setState
은class MyClassComponent extends React.Component {
state = {
counter: 0,
};
incrementCounter = () => {
this.setState((prevState) => ({
counter: prevState.counter + 1,
}));
};
render() {
return (
<button type="button" onClick={this.incrementCounter}>
Increment: {this.state.counter}
</button>
);
}
}
Note: In this case state will be "shallowly" merged too.
너는 아마도 자신에게 이렇게 하는 것은 너무 지나치다고 말할 것이다. 왜냐하면 나는
counter
으로 이전의 this.state.counter
을 방문할 수 있기 때문이다네, 네 말이 맞아요.하지만 당신은:
class MyClassComponent extends React.Component {
state = {
counter: 0,
};
// This will only increment by 1 because when calling the
// the value of `this.state.counter` is 0
// for all 3 `setState`
incrementByThreeCounter = () => {
this.setState({
counter: this.state.counter + 1,
});
this.setState({
counter: this.state.counter + 1,
});
this.setState({
counter: this.state.counter + 1,
});
};
render() {
return (
<button
type="button"
onClick={this.incrementByThreeCounter}
>
Increment: {this.state.counter}
</button>
);
}
}
class FoodOrdering extends React.Component {
state = {
orderInProgressCount: 0,
orderDeliveredCount: 0,
};
order = async () => {
// I tell myself that I can destructure
// `loading` from the state because it used at multiple place
// but it's a bad idea
const { orderInProgressCount, orderDeliveredCount } =
this.state;
this.setState({
orderInProgressCount: orderInProgressCount + 1,
});
await fakeAPI();
// In this case `loading` is still false
this.setState({
orderInProgressCount: orderInProgressCount - 1,
orderDeliveredCount: orderDeliveredCount + 1,
});
};
render() {
const { orderInProgressCount, orderDeliveredCount } =
this.state;
return (
<div>
<p>Order in progress: {orderInProgressCount}</p>
<p>Order delivered: {orderDeliveredCount}</p>
<button type="button" onClick={this.order}>
Order food
</button>
</div>
);
}
}
여기서 놀기:따라서 이전 값이 필요할 때 콜백 API를 사용하는 것이 좋습니다.
우리는 이미 구성 요소 종류를 충분히 놀았으니, 이제 기능 구성 요소에서 어떻게 사용하는지 봅시다.
기능 부품
16.8.6
버전에서는 useState
이 연결되어 있어 상태가 있는 기능 구성 요소를 실현할 수 있다.우리 함께 그것을 어떻게 사용하는지 검사합시다.초기화
상태의 초기 값은
useState
갈고리에 매개 변수로 제공됩니다.다음과 같은 두 가지 방법이 있습니다.import { useState } from "react";
function StateFunctionalComponent() {
// The initial value is 0
useState(0);
return <p>Functional component with state</p>;
}
import { useState } from "react";
function initializeState() {
return 0;
}
function StateFunctionalComponent() {
// The initial value will be
// initialized in a lazy way to 0
useState(initializeState);
return <p>Functional component with state</p>;
}
아래의 초기화는 당신에게 어떤 차이가 있습니까?useState(initializeState());
및useState(initializeState);
뚜렷하지 않죠?사실상 첫 번째 코드에서는
initializeState
이 렌더링할 때마다 호출되고 두 번째 코드는 첫 번째 렌더링에서만 호출된다.고성능 프로세스가 있을 때, 지연 초기화를 사용하면 재미있을 수 있습니다.
어떻게 국가에 들어갑니까
어떻게 방문하는지 알고 싶으면, 우리는 반드시
useState
이 되돌아오는 내용을 보아야 한다.값이 첫 번째 요소이고 업데이트 프로그램이 두 번째 요소인 배열을 반환합니다.
const [value, setValue] = useState('Initial value');
그래서 저는 value
만 사용하면 됩니다.Note: You can name the
value
and theupdater
with the name you want, because there is a destructuring of the array :)
const [counter, setCounter] = useState(0);
상태 업데이트
그리고 상태를 갱신하려면
updater
을 사용하세요.*Component 클래스와 마찬가지로 다음 두 가지 방법이 있습니다.function Counter() {
const [counter, setCounter] = useState(0);
return (
<button type="button" onClick={() => setCounter(100)}>
Change counter: {counter}
</button>
);
}
function Counter() {
const [counter, setCounter] = useState(0);
return (
<button
type="button"
onClick={() => setCounter((prev) => prev + 1)}
>
Increment counter: {counter}
</button>
);
}
에서 설명한 것과 같은 이유로 이전 값이 필요할 때 콜백 API를 사용하는 것이 좋습니다.기능 구성 요소의 상태에 대해 알아야 할 것
자동으로 병합이 완료되지 않았습니다.
함수 구성 요소의 상태를 업데이트할 때 상태를 병합하지 않습니다.따라서 주에 객체가 있는 경우 업데이트 중에 전달되지 않은 모든 키가 삭제됩니다.
function Person() {
const [person, setPerson] = useState({
firstName: "Bob",
lastName: "TheSponge",
});
const updateFirstName = () => {
// When doing that you will lose the lastName key
// in your person object
setPerson({ firstName: "Romain" });
};
return (
<div>
<p>First name: {firstName}</p>
<p>Last name: {lastName}</p>
<button type="button" onClick={updateFirstName}>
Update firstName
</button>
</div>
);
}
함수를 상태에 저장
useState
의 API는 상태를 초기화하고 업데이트할 때 리셋할 수 있기 때문입니다.함수를 저장하려면 두 프로세스 중 콜백 API를 사용해야 합니다. 그렇지 않으면 함수가 실행되고 반환 값이 저장됩니다.function firstFunction() {
// Do some stuff
return "Hello";
}
function secondFunction() {
// Do some stuff
return "Guys and girls";
}
export default function MyComponent() {
// If you do `useState(firstFunction)`
// It will be 'Hello' that will be stored
const [myFunction, setMyFunction] = useState(
() => firstFunction
);
const changeFunction = () => {
// If you do `setMyFunction(secondFunction)`
// It will be 'Guys and girls' that will be stored
setMyFunction(() => secondFunction);
};
return (
<button type="button" onClick={changeFunction}>
Change the function stored: {myFunction.toString()}
</button>
);
}
비동기 코드 사용
대부분의 경우 React는 일괄 처리 상태를 업데이트하여 단일 렌더링을 생성합니다.예를 들어
useEffect
/useLayoutEffect
과 이벤트 처리 프로그램에서예를 들어, 다음 코드에서 버튼을 클릭하면 새
firstName
및 lastName
을 사용하여 단일 렌더링이 생성됩니다.function MyComponent() {
const [firstName, setFirstName] = useState("Bob");
const [lastName, setLastName] = useState("TheSponge");
return (
<button
type="button"
onClick={() => {
setFirstName("Patrick");
setLastName("Star");
}}
>
Change name
</button>
);
}
그러나 비동기식 코드를 사용하는 경우 예를 들어 REST API를 사용하여 새 이름을 가져오면 여러 개의 표현이 발생합니다.function fakeAPI() {
return new Promise((resolve) =>
setTimeout(
() =>
resolve({ firstName: "Patrick", lastName: "Star" }),
500
)
);
}
function MyComponent() {
const [firstName, setFirstName] = useState("Bob");
const [lastName, setLastName] = useState("TheSponge");
return (
<button
type="button"
onClick={async () => {
const newName = await fakeAPI();
// It will result into 2 render
// firstName: 'Patrick' and lastName: 'TheSponge'
// firstName: 'Patrick' and lastName: 'Star'
setFirstName(newName.firstName);
setLastName(newName.lastName);
}}
>
Change name
</button>
);
}
이러한 상황에서 우리는 firstName
과 lastName
의 값을 동시에 가지기를 원한다. 왜냐하면 이 값들은 한데 묶여 있기 때문이다.그러나 업데이트된 값은 상관없을 수도 있지만, 우리는 때때로 함께 업데이트를 해야 한다. 이런 상황에서 우리는 단독 상태 업데이트를 실행할 것이며, 상태 업데이트의 순서에 주의해야 한다.Note: With React v18 these cases will not happen anymore, and updates will be also batched.
Note: In a next article, we will see how the batching of state works under the hood and how we can force the batching of updates in an application.
국가와 무슨 관계가 있는가
이 규칙은 구성 요소 클래스와 기능 구성 요소에 모두 유효합니다.한 가지 상태를 바꾸지 마라.
예를 들어, 이렇게 하지 마십시오.
function Person() {
const [person, setPerson] = useState({
firstName: "Bob",
lastName: "TheSponge",
});
return (
<div>
<p>First name: {firstName}</p>
<p>Last name: {lastName}</p>
<button
type="button"
onClick={() =>
setPerson(
(prevState) => (prevState.firstName = "Romain")
)
}
>
Update firstName
</button>
</div>
);
}
왜 안 돼?업데이트 리셋을 호출할 때, React는 새로운 상태와 엄격하게 비교되며, 만약 같으면, React는 다시 렌더링을 터치하지 않습니다.
Note: And do
person.firstName = 'Romain'
will do nothing at all.
결론
React state를 사용하는 것은 어렵지 않으며 이를 제대로 사용하는 방법을 이해하는 것이 중요합니다.
성능 비용 때문에 성능 구성 요소에서 상태를 초기화하려면 리셋 초기화를 사용하십시오.
마지막으로 상태가 UI에 사용되지 않으면
state
을 사용하는 것이 옳지 않을 수도 있고 ref
(useRef
)을 사용하는 것이 더 좋은 선택일 수도 있다.다음 기사에서 확인할 수 있습니다.)언제든지 의견을 올려주시고 더 많은 정보를 원하신다면 계속해서 저를 팔로우하거나 저의 Website을 방문해 주십시오.
Reference
이 문제에 관하여(반응 상태에 대해 알아야 할 것), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/romaintrotard/things-you-need-to-know-about-react-state-2l8o텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)