렌더 소품 및 고차 컴포넌트

14797 단어 reactjavascript
Cover image by Graffiti Picture Taker, on Flickr

지난 주에 저는 최초의 dev.to 콘테스트에 참가하여 서버리스 멀티플레이어 클리커 게임을 제출했습니다.



그 대가로 노하우도 알려드리고 싶습니다.


React 개발자이고 몇 년 동안 생태계를 따라왔다면 최근에 render props(RP) 또는 기능이 자식으로 등장하는 것을 눈치 챘을 것입니다.

항상 사람들은 고차 구성 요소(HoC)에 대해 이야기했는데 이제 이것은?

글쎄, 나도 혼란스러웠지만 React 프로그래밍 방식을 고려한다면 RP가 완전히 의미가 있음을 알게 될 것입니다.



렌더 소품은 단순히 렌더 호출에 사용되는 소품입니다. 요소를 반환해야 하는 함수를 사용합니다. 이 함수는 또한 인수를 통해 일부 동적 데이터를 가져오며 반환된 요소에서 사용할 수 있습니다.

그들은 HoC에 대한 의존성 주입 대안입니다.



RP 기반 구성 요소에서 요소를 만들 때마다 다른 요소를 해당 RP에 전달할 수 있습니다. HoC는 렌더링 시간이 아니라 정의 시간에 구성 요소를 래핑합니다.

지난 몇 년 동안 중첩 요소를 생성하기 위해 종속성 주입을 사용하는 것이 React 코딩 관행에서 일반적이 되었으며, RP는 해당 원칙의 자연스러운 확장입니다.

예를 들어 다음과 같이 List 구성 요소를 정의하지 않습니다.

const List = props => <ul>{props.data.map(i => <ListItem text={i}/>)}</ul>;
const ListItem = props  => <li>{props.text}</li>;

// usage
<List data={["hello", "world"]}/>


이제 Listdata 및 렌더링해야 하는 ListItem에 대해 알아야 하기 때문입니다.

대신 다음과 같이 정의합니다.

const List = props => <ul>{props.children}</ul>;
const ListItem = props  => <li>{props.text}</li>;

// usage
<List>
  {data.map(i => <ListItem text={i}/>)}
</List>


이제 data 및 자식 구성 요소를 List에 주입할 수 있고 렌더링만 하면 되기 때문입니다. 예를 들어 ActiveListItem에 대해 알 필요가 없는 다른 것List을 던질 수 있습니다.

RP가 있는 구성 요소는 이것과 정말 잘 어울립니다. 상상해보십시오. 귀하의 List는 단순히 모든 children를 렌더링하고 수집 한 일부 데이터를 전달합니다.

고차 가져오기



HoC는 이를 수행하는 또 다른 방법이지만, 그 배후의 아이디어는 몇 가지 추가 기능이 있는 모든 곳에서 사용할 수 있는 wrapped 구성 요소를 만드는 것입니다.

HoC는 다음과 같이 보일 수 있습니다.

const wrapWithFetch = Wrapped => class Fetch extends React.Component {
  state = { result: null };

  componentDidMount() {
    fetch(this.props.url)
    .then(r => r.json())
    .then(result => this.setState({result}))
  }

  render() {
    const {result} = this.state;
    return result? <Wrapped data={result}/> : null;
  }
}

// Stateless component that displays text
const Text = ({data})=> <p>{data.name}</p>;

// Wrappted text that gets data
const FetchText = wrapWithFetch(Text);

// Usage
<FetchText url="/user/123"/>


렌더 소품 가져오기



RP 버전은 다음과 같습니다.

class Fetch extends React.Component {
  state = { result: null };

  componentDidMount() {
    fetch(this.props.url)
    .then(r => r.json())
    .then(result => this.setState({result}))
  }

  render() {
    const {result} = this.state;
    return result? this.props.render(result) : null;
  }
}

// usage
<Fetch url="/user/123" render={user => <p>{user.name}</p>}/>


마운트되면 일부 데이터를 가져와 RP에 전달합니다.
children는 소품이므로 사용자 지정 소품 대신 사용할 수도 있습니다.

<Fetch url="/user/123">{user =>
  <p>{user.name}</p>
}</Fetch>


그러면 다음과 같은 Fetch 구성 요소가 생성됩니다.

class Fetch extends React.Component {
  state = { result: null };

  componentDidMount() {
    fetch(this.props.url)
    .then(r => r.json())
    .then(result => this.setState({result}))
  }

  render() {
    const {result} = this.state;
    return result? this.props.children(result) : null;
  }
}


상상할 수 있듯이 이제 모든 자식을 서버에서 데이터를 수신하고 데이터를 사용할 수 있을 때만 렌더링되는 함수로 래핑할 수 있습니다.

결론



Render Props를 사용하여 앱에 더 많은 종속성 주입을 추가하여 훨씬 유연하게 변경할 수 있습니다.

RP에 새 요소를 추가하여 표시되는 내용을 간단히 변경할 수 있습니다(예: 테이블을 그래프로 변경하는 등).

그러나 랩핑 RP 구성 요소를 변경하여 자식이 이제 다른 소스에서 데이터를 수신하도록 할 수도 있지만 자식을 변경할 필요는 없습니다. RP 인수의 데이터를 올바른 자식 소품에 매핑할 수 있기 때문입니다. 파리.

대회



또한 이 게시물이 마음에 드셨다면:

좋은 웹페이지 즐겨찾기