React 에서 크로스 구성 요소 배포 상 태 를 상세 하 게 설명 하 는 세 가지 방법

내 가 백 번 째 로 물 었 을 때,나 는 전형 적 인 CRUD 화면 을 연구 하고 있 었 다."이 구성 요소 에 상 태 를 유지 해 야 합 니까?아니면 부모 구성 요소 로 이동 해 야 합 니까?"
하위 구성 요소 의 상 태 를 가볍게 제어 해 야 한다 면.같은 문제 에 부 딪 히 셨 을 수도 있 습 니 다.
간단 한 예 와 세 가지 복구 방법 을 통 해 그것 을 되 돌아 보 자.앞의 두 가지 방법 은 흔히 볼 수 있 는 방법 이 고,세 번 째 방법 은 그다지 일반적인 방법 이 아니다.
문제
제 뜻 을 보 여 드 리 기 위해 서 간단 한 책 CRUD(번역자 주:추가(Create),조회 읽 기(Retrieve),업데이트(Update),삭제(Delete)화면 을 사용 하 겠 습 니 다.

우 리 는 세 가지 구성 부분 이 있다.<BookList /> 은 책 과 단추 목록 을 편집 하 는 데 사용 되 는 구성 요소 입 니 다.<BookForm /> 은 책 에 대한 변경 사항 을 저장 하기 위해 두 개의 입력 과 단 추 를 누 릅 니 다.그리고 다른 두 구성 요 소 를 포함 하 는 <BookApp />.
그렇다면 우리 의 상 태 는 무엇 일 까?좋 습 니 다.<북 앱/>은 현재 편집 중인 책의 내용 을 추적 하고 식별 해 야 합 니 다.상태 가 없습니다.또한는'저장'단 추 를 누 를 때 까지 입력 한 현재 상 태 를 유지 해 야 합 니 다.

import React, { Component } from "react";
import { render } from "react-dom";

const books = [
 {
  title: "The End of Eternity",
  author: "Isaac Asimov"
 },
 //...
];

const BookList = ({ books, onEdit }) =&gt; (
 <table>
  <tr>
   <th>Book Title</th>
   <th>Actions</th>
  </tr>
  {books.map((book, index) =&gt; (
   <tr>
    <td>{book.title}</td>
    <td>
     &lt;button onClick={() =&gt; onEdit(index)}&gt;Edit&lt;/button&gt;
    </td>
   </tr>
  ))}
 </table>
);

class BookForm extends Component {
 state = { ...this.props.book };
 render() {
  if (!this.props.book) return null;
  return (
   &lt;form&gt;
    <h3>Book</h3>
    &lt;label&gt;
     Title:
     &lt;input
      value={this.state.title}
      onChange={e =&gt; this.setState({ title: e.target.value })}
     /&gt;
    &lt;/label&gt;
    &lt;label&gt;
     Author:
     &lt;input
      value={this.state.author}
      onChange={e =&gt; this.setState({ author: e.target.value })}
     /&gt;
    &lt;/label&gt;
    &lt;button onClick={() =&gt; this.props.onSave({ ...this.state })}&gt;
     Save
    &lt;/button&gt;
   &lt;/form&gt;
  );
 }
}

class BookApp extends Component {
 state = {
  books: books,
  activeIndex: -1
 };
 render() {
  const { books, activeIndex } = this.state;
  const activeBook = books[activeIndex];
  return (
   <div>
    &lt;BookList
     books={books}
     onEdit={index =&gt;
      this.setState({
       activeIndex: index
      })}
    /&gt;
    &lt;BookForm
     book={activeBook}
     onSave={book =&gt;
      this.setState({
       books: Object.assign([...books], { [activeIndex]: book }),
       activeIndex: -1
      })}
    /&gt;
   </div>
  );
 }
}

render(&lt;BookApp /&gt;, document.getElementById("root"));
보기 에는 괜 찮 은 데 그 는 소 용이 없다.
구성 요소 인 스 턴 스 를 만 들 때상 태 를 초기 화 합 니 다.따라서 목록 에서 다른 책 을 선택 할 때 부모 급 은 변경 이 필요 하 다 는 것 을 알 수 없습니다.
우 리 는 어떻게 그것 을 복원 합 니까?
방법 1:제어 모듈
일반적인 방법 은 상 태 를 향상 시 키 고를 제어 되 는 구성 요소 로 전환 하 는 것 입 니 다.<북 폼/>상 태 를 삭제 하고 activeBook 을<북 앱/>상태 에 추가 하 며,<북 폼/>에 onChange 도 구 를 추가 합 니 다.입력 할 때마다 호출 합 니 다.

//...

class BookForm extends Component {
 render() {
  if (!this.props.book) return null;
  return (
   &lt;form&gt;
    <h3>Book</h3>
    &lt;label&gt;
     Title:
     &lt;input
      value={this.props.book.title}
      onChange={e =&gt;
       this.props.onChange({
        ...this.props.book,
        title: e.target.value
       })}
     /&gt;
    &lt;/label&gt;
    &lt;label&gt;
     Author:
     &lt;input
      value={this.props.book.author}
      onChange={e =&gt;
       this.props.onChange({
        ...this.props.book,
        author: e.target.value
       })}
     /&gt;
    &lt;/label&gt;
    &lt;button onClick={() =&gt; this.props.onSave()}&gt;Save&lt;/button&gt;
   &lt;/form&gt;
  );
 }
}

class BookApp extends Component {
 state = {
  books: books,
  activeBook: null,
  activeIndex: -1
 };
 render() {
  const { books, activeBook, activeIndex } = this.state;
  return (
   <div>
    &lt;BookList
     books={books}
     onEdit={index =&gt;
      this.setState({
       activeBook: { ...books[index] },
       activeIndex: index
      })}
    /&gt;
    &lt;BookForm
     book={activeBook}
     onChange={book =&gt; this.setState({ activeBook: book })}
     onSave={() =&gt;
      this.setState({
       books: Object.assign([...books], { [activeIndex]: activeBook }),
       activeBook: null,
       activeIndex: -1
      })}
    /&gt;
   </div>
  );
 }
}

//...
지금 은 일 을 할 수 있 지만 나 에 게 는 &lt;BookForm /&gt; 의 상 태 를 향상 시 키 는 것 이 옳지 않다.사용자 가'저장'을 누 르 기 전에 &lt;BookApp /&gt; 은 책 에 대한 변경 에 관심 이 없습니다.그러면 왜 자신의 상 태 를 유지 해 야 합 니까?
방법 2:동기 state
지금 은 일 을 할 수 있 지만 저 에 게 는의 상 태 를 향상 시 키 는 것 이 옳지 않 습 니 다.사용자 가'저장'을 누 르 기 전에<북 앱/>은 책 에 대한 변경 사항 에 관심 이 없습니다.왜 자신의 상 태 를 유지 해 야 합 니까?

//...
class BookForm extends Component {
 state = { ...this.props.book };
 componentWillReceiveProps(nextProps) {
  const nextBook = nextProps.book;
  if (this.props.book !== nextBook) {
   this.setState({ ...nextBook });
  }
 }
 render() {
  if (!this.props.book) return null;
  return (
   &lt;form&gt;
    <h3>Book</h3>
    &lt;label&gt;
     Title:
     &lt;input
      value={this.state.title}
      onChange={e =&gt; this.setState({ title: e.target.value })}
     /&gt;
    &lt;/label&gt;
    &lt;label&gt;
     Author:
     &lt;input
      value={this.state.author}
      onChange={e =&gt; this.setState({ author: e.target.value })}
     /&gt;
    &lt;/label&gt;
    &lt;button onClick={() =&gt; this.props.onSave({ ...this.state })}&gt;
     Save
    &lt;/button&gt;
   &lt;/form&gt;
  );
 }
}
//...
이 방법 은 단일 한 사실 원 을 가 진 다 는 React 의 생각 에 어 긋 나 기 때문에 일반적으로 나 쁜 방법 으로 여 겨 진다.나 는 이런 상황 인지 확실 하지 않 지만,동기 상태 가 항상 그렇게 쉬 운 것 은 아니다.그 밖 에 나 는 가능 한 한 생명주기 방법 을 사용 하 는 것 을 피한다.
방법 3:키 가 제어 하 는 구성 요소
그런데 왜 우 리 는 낡은 상 태 를 회수 해 야 합 니까?사용자 가 책 을 선택 할 때마다 새로운 상 태 를 가 진 새로운 인 스 턴 스 가 의미 가 있 지 않 습 니까?
이 를 위해 서 는 React 에 게 오래된 인 스 턴 스 를 사용 하지 않 고 새로운 인 스 턴 스 를 만 드 는 것 을 알려 야 합 니 다.이것 이 바로 키 프로 프 의 용도 다.

//...
class BookApp extends Component {
 state = {
  books: books,
  activeIndex: -1
 };
 render() {
  const { books, activeIndex } = this.state;
  const activeBook = books[activeIndex];
  return (
   <div>
    &lt;BookList
     books={books}
     onEdit={index =&gt;
      this.setState({
       activeIndex: index
      })}
    /&gt;
    &lt;BookForm
     key={activeIndex}
     book={activeBook}
     onSave={book =&gt;
      this.setState({
       books: Object.assign([...books], { [activeIndex]: book }),
       activeIndex: -1
      })}
    /&gt;
   </div>
  );
 }
}
//...
요소 가 이전 렌 더 링 과 다른 키 를 가지 고 있다 면 React 는 새로운 인 스 턴 스 를 만 들 것 입 니 다.따라서 사용자 가 새 책 을 선택 할 때키 가 변경 되면 구성 요소 의 새로운 인 스 턴 스 를 만 들 고 props 에서 상 태 를 초기 화 합 니 다.
무슨 소득 이 있 습 니까?구성 요소 인 스 턴 스 를 다시 사용 하 는 것 은 더 적은 DOM 변 이 를 의미 하 며 더 좋 은 성능 을 의미 합 니 다.따라서 React 가 구성 요소 의 새로운 인 스 턴 스 를 만 들 도록 강제 할 때,우 리 는 추가 적 인 DOM 돌변 을 위해 약간의 비용 을 받 을 것 입 니 다.그러나 이러한 상황 에 대해 서 는 이러한 비용 이 가장 적 고 키 는 변화 가 빠 르 지 않 으 며 구성 요소 가 크 지 않 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기