React의 반복 렌더링: 일반 JSON 렌더링 구축

41215 단어 recursionreactjson
작년에 저는 일을 위해서든 만족도를 위해서든 React와 광범위하게 협력해 왔습니다.나는 우연히 매우 재미있는 패턴을 발견했지만, React 구성 요소를 렌더링하는 데 사용되는 것을 본 적이 없다.만약 네가 컴퓨터 과학 교육을 받은 적이 있다면, 너는 귀착이 무엇인지 일찌감치 알고 있을 것이다.귀속은 본질적으로 파라미터가 우리가 정의한 어떤 기본적인 상황일 때까지 현재 있는 완전히 같은 함수를 호출하는 것이다.
최근에 제 임무는 API를 통해 얻은 JSON을 보여 주는 React 구성 요소를 만드는 것입니다.만약 당신이 웹 개발자라면, 당신은 API가 무엇을 되돌릴지 영원히 백 퍼센트 확신할 수 없다는 것을 알 수 있을 것이다. 만약 당신이 그렇게 생각하지 않는다면, 나는 당신이 생각해 보라고 건의한다. 아마도 당신은 생각을 바꿀 것이다.웹은 정적 형식이 아닙니다.본고에서 우리는 API가 항상 어떤 JSON을 되돌린다고 가정한다.
내가 보여야 할 JSON은 추악한 끼워 넣은 JSON으로 여러 차원을 가지고 있다.너는 이 등급들이 채워질지, 그것이 빈수조인지 빈수조인지 영원히 알 수 없다. 가장 간단한 방법은 각 차원 구조의 등급을 위한 구성 요소를 만드는 것이다. 몇 분 후, 나는 이 등급들을 점차적으로 보여 줄 생각이 생겼다. 흥분된다!컴퓨터 프로그래머로서 나는 이런 문제를 귀속시키고 해결하는 재미있는 방법을 절대 좋아한다.

어셈블리 생성


우리가 테스트할 위조 JSON은 JSON Generator 로 생성된 것이다.보시다시피 빈 값, 빈 그룹, 빈 대상, 빈 값이 있는 그룹, 빈 값이 있는 대상이 있습니다.우리의 최대 깊이는 4층이다.
const testJson = {
  "_id": "5bc32f3f5fbd8ad01f8265fd",
  "index": 0,
  "guid": "87cfbb5d-71fb-45a7-b268-1df181da901c",
  "isActive": true,
  "balance": "$3,583.12",
  "picture": "http://placehold.it/32x32",
  "age": 31,
  "eyeColor": "brown",
  "nullTestValue": null,
  "arrayWithNulls": [null, null, null],
  "objectWithNulls": {
     "firstNullValue": null,
     "secondNullValue": null     
  },
  "name": "Becky Vega",
  "gender": "female",
  "company": "ZOID",
  "email": "[email protected]",
  "phone": "+1 (957) 480-3973",
  "address": "426 Hamilton Avenue, Holtville, New Hampshire, 3431",
  "about": "Duis do occaecat commodo velit exercitation aliquip mollit ad reprehenderit non cupidatat dolore ea nulla. Adipisicing ea voluptate qui sunt non culpa labore reprehenderit qui non. Eiusmod ad do in quis cillum sint pariatur. Non laboris ullamco ea voluptate et anim qui quis id exercitation mollit ullamco dolor incididunt. Ad consequat anim velit culpa. Culpa Lorem eiusmod cupidatat dolore aute quis sint ipsum. Proident voluptate occaecat nostrud officia.\r\n",
  "registered": "2016-11-19T01:14:28 -01:00",
  "latitude": -80.66618,
  "longitude": 65.090852,
  "tags": [
    "ea",
    "officia",
    "fugiat",
    "anim",
    "consequat",
    "incididunt",
    "est"
  ],
  "friends": [
    {
      "id": 0,
      "name": "Genevieve Cooke",
      "ownFriends": {
         "1": "Rebbeca",
         "2": "Julia",
         "3": "Chopper only"
      },
    },
    {
      "id": 1,
      "name": "Eaton Buck"
    },
    {
      "id": 2,
      "name": "Darla Cash"
    }
  ],
  "greeting": "Hello, Becky Vega! You have 8 unread messages.",
  "favoriteFruit": "strawberry"
}
우선 TypeScript를 사용하여 새 React 프로젝트를 만듭니다. 누가 정적 유형을 좋아하지 않습니까?)
yarn create react-app recursive-component --scripts-version=react-scripts-ts
다음은 JSON을 보여줄 새로운 React 구성 요소를 만들 수 있습니다.우리는 귀속 속성(RecursiveProperty)이라고 할 수 있습니다.기본 상황에 도달할 때 단일 JSON 속성과 값이 나타나기 때문입니다.
우리의 구성 요소와 파일 구조는 다음과 같다.
import * as React from 'react';

interface IterableObject {
  [s: number]: number | string | boolean | IterableObject;
}

interface Props {
  property: number | string | boolean | IterableObject;
  propertyName: string;
  rootProperty?: boolean;
  excludeBottomBorder: boolean;
}

const RecursiveProperty: React.SFC<Props> = props => {

  return(
    <div>Our future component</div>
  );
}

export default RecursiveProperty;

우리는 이제 응용 프로그램에서 이 구성 요소를 렌더링할 수 있습니다.tsx.
import * as React from 'react';
import './App.css';

import logo from './logo.svg';
import RecursiveProperty from './RecursiveProperty';

class App extends React.Component {
  public render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <div className="App-intro">
          <RecursiveProperty property={testJson} propertyName="Root Property" excludeBottomBorder={false} rootProperty={true}/>
        </div>
      </div>
    );
  }
}

export default App;

const testJson = ...
나는 text-align: center 클래스에서 App.css 를 삭제하고 margin: 0 auto 클래스와 width: 60% 클래스에 추가하여 목록을 가운데에 잘 놓을 것이다.
다음으로 우리는 우리의 조건을 써야 한다.어셈블리는 속성이 잎(계층 구조 트리의 마지막 노드)인지 확인해야 합니다.이 경우 속성 이름과 값이 표시됩니다.없으면 구성 요소를 다시 호출하고 다음 차원 구조 단계를 속성으로 전달합니다.
스타일을 추가하기 위해 모든 속성에 용기를 만들 것입니다. (스타일링 구성 요소 사용)용기는 각 단계가 이전 단계보다 조금 더 축소될 수 있도록 왼쪽 거리 집합이 있을 것이다.
이런 상황에서 우리는 잎의 속성만 과장하려고 시도할 것이다.우리의 JSON에 대해 "그것은 잎이 아닙니다"만 보일 것입니다. 왜냐하면 JSON 문서의 뿌리는 iterable 대상이기 때문에 우리는 잠시 후에 그것을 처리할 것입니다.우리는 잎이 항상 세 가지 기본 JSON 유형 중 하나인 블, 문자열, 숫자여야 한다는 것을 안다.
import * as React from 'react';
import styled from 'styled-components';

interface IterableObject {
  [s: string]: number | string | boolean | IterableObject;
}

interface Props {
  property: number | string | boolean | IterableObject;
  propertyName: string;
  rootProperty?: boolean;
  excludeBottomBorder: boolean;
}

const RecursivePropertyContainer = styled.div`
  padding-top: 10px;
  padding-left: 3px;
  margin-left: 10px;
  ${(props: { excludeBottomBorder: boolean }) =>
    props.excludeBottomBorder ? '' : 'border-bottom: 1px solid #b2d6ff;'}
  color: #666;    
  font-size: 16px;
`;

export const PropertyName = styled.span`
  color: black;
  font-size: 14px;
  font-weight: bold;
`;

const RecursiveProperty: React.SFC<Props> = props => {
  return (
    <RecursivePropertyContainer excludeBottomBorder={props.excludeBottomBorder}>
      {props.property ? (
        typeof props.property === 'number' ||
        typeof props.property === 'string' ||
        typeof props.property === 'boolean' ? (
          <React.Fragment>
            <PropertyName>{camelCaseToNormal(props.propertyName)}: </PropertyName>
            {props.property.toString()}
          </React.Fragment>
        ) : (
          "It isn't a leaf"
        )
      ) : (
        'Property is empty'
      )}
    </RecursivePropertyContainer>
  );
};

const camelCaseToNormal = (str: string) => str.replace(/([A-Z])/g, ' $1').replace(/^./, str2 => str2.toUpperCase());

export default RecursiveProperty;
camelCaseToNormal 방법은 매우 간단합니다. camelCaseToNormal 텍스트를 빈칸이 있는 일반 텍스트로 변환합니다.
다음으로, 우리는 다음 단계를 사용하여 이 구성 요소를 다시 호출해야 한다.우리는 JSON의 데이터 목록 - 하나의 대상 그룹, 또는 키/값이 맞는iterable 대상을 나타내는 두 가지 방법이 있습니다.이 두 가지 상황에 대해 우리는 속성을 새로운 RecursiveProperty에 비추어야 한다.
만약 우리가iterable 대상이 있다면,object를 사용할 것입니다.values () 방법은 값 그룹을 가져옵니다. (이것은 ES7 방법이므로 tsconfig.json의lib 속성에 포함해야 합니다.)속성 이름을 하위 레벨에 전달하기 위해 Object를 사용합니다.getOwnPropertyNames () 메서드이것은 특정한 이름에 안전하게 접근할 수 있는 속성 명수 그룹을 되돌려줍니다.map () 메서드입니다.이 방법의 장점은 속성 키가 아닌 색인을 되돌려 주는 수조를 처리할 수 있다는 데 있다.
우리 구성 요소return () 이 이렇게 보입니다.
return (
  <RecursivePropertyContainer excludeBottomBorder={props.excludeBottomBorder}>
    {props.property ? (
      typeof props.property === 'number' ||
      typeof props.property === 'string' ||
      typeof props.property === 'boolean' ? (
        <React.Fragment>
          <PropertyName>{camelCaseToNormal(props.propertyName)}: </PropertyName>
          {props.property.toString()}
        </React.Fragment>
      ) : (
        Object.values(props.property).map((property, index, { length }) => (
          <RecursiveProperty
            key={index}
            property={property}
            propertyName={Object.getOwnPropertyNames(props.property)[index]}
            excludeBottomBorder={index === length - 1}
          />
        ))
      )
    ) : (
      'Property is empty'
    )}
  </RecursivePropertyContainer>
);
이제 중첩된 객체를 축소하고 확장하고 초기 렌더링된 잎 값만 표시할 수 있다면 좋습니다.
ExpandableProperty라는 새 구성 요소를 만들 수 있습니다.
import * as React from 'react';
import styled from 'styled-components';

export const PropertyName = styled.div`
  color: #008080;
  font-size: 14px;
  font-weight: bold;
  cursor: pointer;
`;

interface Props {
  title: string;
  expanded?: boolean;
}

interface State {
  isOpen: boolean;
}

export default class ExpandableProperty extends React.Component<Props, State> {
  state = {
    isOpen: !!this.props.expanded
  };

  render() {
    return (
      <React.Fragment>
        <PropertyName onClick={() => this.setState({ isOpen: !this.state.isOpen })}>
          {this.props.title}
          {this.state.isOpen ? '-' : '+'}
        </PropertyName>
        {this.state.isOpen ? this.props.children : null}
        {React.Children.count(this.props.children) === 0 && this.state.isOpen ? 'The list is empty!' : null}
      </React.Fragment>
    );
  }
}
우리는 이제 끝낼 수 있다.이 구성 요소의 맵 () 방법은 필요할 때 확장할 수 있도록 합니다.
return (
  <RecursivePropertyContainer excludeBottomBorder={props.excludeBottomBorder}>
    {props.property ? (
      typeof props.property === 'number' ||
      typeof props.property === 'string' ||
      typeof props.property === 'boolean' ? (
        <React.Fragment>
          <PropertyName>{camelCaseToNormal(props.propertyName)}: </PropertyName>
          {props.property.toString()}
        </React.Fragment>
      ) : (
        <ExpandableProperty title={camelCaseToNormal(props.propertyName)} expanded={!!props.rootProperty}>
          {Object.values(props.property).map((property, index, { length }) => (
            <RecursiveProperty
              key={index}
              property={property}
              propertyName={Object.getOwnPropertyNames(props.property)[index]}
              excludeBottomBorder={index === length - 1}
            />
          ))}
        </ExpandableProperty>
      )
    ) : (
      'Property is empty'
    )}
  </RecursivePropertyContainer>
);
마지막으로, 우리는 그것이 행동하는 것을 볼 수 있다.

봐라, 우리가 방금 쓸모 있는 물건을 좀 만들었어!귀속은 React와 잘 어울린다. 이것은 아주 좋은 도구이다. 나는 장래에 반드시 그것을 더 많이 사용할 것이다.나는 나도 네가 그것을 사용하도록 격려하길 바란다. 그것은 사람을 물지 않을 것이다.
소스 코드는 react-recursive-component 에서 찾을 수 있습니다.
건배!

좋은 웹페이지 즐겨찾기