React.js 양식 구성 요소에서 상태 또는 참조를 사용합니까?


116

React.js로 시작하고 간단한 양식을 작성하고 싶지만 문서에서 두 가지 방법을 찾았습니다.

번째Refs를 사용하는 입니다 .

var CommentForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var author = React.findDOMNode(this.refs.author).value.trim();
    var text = React.findDOMNode(this.refs.text).value.trim();
    if (!text || !author) {
      return;
    }
    // TODO: send request to the server
    React.findDOMNode(this.refs.author).value = '';
    React.findDOMNode(this.refs.text).value = '';
    return;
  },
  render: function() {
    return (
      <form className="commentForm" onSubmit={this.handleSubmit}>
        <input type="text" placeholder="Your name" ref="author" />
        <input type="text" placeholder="Say something..." ref="text" />
        <input type="submit" value="Post" />
      </form>
    );
  }
});

그리고 두 번째는 사용 상태 (가) 성분 반작용 내부 :

var TodoTextInput = React.createClass({
  getInitialState: function() {
    return {
      value: this.props.value || ''
    };
  },

  render: function() /*object*/ {
    return (
      <input className={this.props.className}
      id={this.props.id}
      placeholder={this.props.placeholder}
      onBlur={this._save}
      value={this.state.value}
      />
    );
  },

  _save: function() {
    this.props.onSave(this.state.value);
    this.setState({value: ''
  });
});

두 가지 대안이 있다면 장단점을 볼 수 없습니다. 감사.


여기에 뭔가 빠졌나요? 양식 값을 얻기 위해 이벤트 객체를 사용하지 않는 이유는 무엇입니까? 이것이 처음에 여기에서 양식을 사용하는 유일한 이유 인 것 같습니다. 기본 제출 동작을 사용하지 않고 입력에 대한 참조가있는 경우 양식으로 래핑 할 필요가 없습니다.
NectarSoft

답변:


143

짧은 버전 : refs를 피하십시오.


유지 관리에 좋지 않으며 WYSIWYG 모델 렌더링이 제공하는 단순성을 많이 잃습니다.

양식이 있습니다. 양식을 재설정하는 단추를 추가해야합니다.

  • 심판 :
    • DOM 조작
    • render는 3 분 전에 양식이 어떻게 보 였는지 설명합니다.
  • 상태
    • setState
    • render는 양식이 어떻게 보이는지 설명합니다.

입력에 CCV 번호 필드가 있고 응용 프로그램에 숫자 인 다른 필드가 있습니다. 이제 사용자는 숫자 만 입력하도록 강제해야합니다.

  • 심판 :
    • onChange 핸들러를 추가합니다 (우리는 이것을 피하기 위해 refs를 사용하지 않습니까?).
    • 숫자가 아닌 경우 onChange에서 dom 조작
  • 상태
    • 이미 onChange 핸들러가 있습니다.
    • if 문을 추가하고, 유효하지 않으면 아무 작업도하지 않습니다.
    • render는 다른 결과를 생성 할 때만 호출됩니다.

어, 신경 쓰지 마세요, PM은 그것이 유효하지 않다면 우리가 빨간 상자 그림자를하기를 원합니다.

  • 심판 :
    • onChange 핸들러가 forceUpdate 또는 무언가를 호출하도록 만드시겠습니까?
    • 렌더 출력을 기반으로 ... 응?
    • 렌더링에서 유효성을 검사 할 값은 어디에서 얻습니까?
    • 요소의 className dom 속성을 수동으로 조작 하시겠습니까?
    • 나는 길을 잃었다
    • 심판없이 다시 작성 하시겠습니까?
    • 우리가 마운트 된 경우 렌더링의 dom에서 읽지 않으면 유효하다고 가정합니까?
  • 상태:
    • if 문 제거
    • this.state를 기반으로 렌더링 유효성을 검사하십시오.

우리는 부모에게 통제권을 돌려줘야합니다. 데이터는 이제 소품에 있으며 변경 사항에 대응해야합니다.

  • 심판 :
    • componentDidMount, componentWillUpdate 및 componentDidUpdate 구현
    • 이전 소품을 수동으로 비교
    • 최소한의 변경으로 dom 조작
    • 야! 우리는 react in react를 구현하고 있습니다.
    • 더 있지만 손가락이 아파
  • 상태:
    • sed -e 's/this.state/this.props/' 's/handleChange/onChange/' -i form.js

사람들은 심판이 상태를 유지하는 것보다 '더 쉽다'고 생각합니다. 이것은 처음 20 분 동안은 사실 일 수 있지만 그 이후의 경험으로는 사실이 아닙니다. "물론, 몇 가지 구성 요소 만 다시 작성하겠습니다."가 아니라 "예, 5 분 안에 완료하겠습니다"라고 말할 수있는 자세를 취하십시오.


3
sed -e 's / this.state / this.props /' 's / handleChange / onChange /'-i form.js에 대해 좀 더 설명해 주시겠습니까?
gabrielgiussi

1
아니요, 돔에 대한 실제 변경을 의미합니다. React.findDOMNode(this.refs.foo). 예를 들어 변경하면 this.refs.foo.props.bar아무 일도 일어나지 않습니다.
Brigand

1
예를 들어으로 <input onChange={this.handleChange} value={this.state.foo} />변경 <input onChange={this.props.handleChange} value={this.props.foo} />했거나 props에서 콜백을 호출하도록 handleChange 함수를 수정 한 경우. 어느 쪽이든, 약간의 명백한 변화입니다.
산적

4
내가 당신의 대답을 조금 혼란스럽게 찾는 유일한 사람인지 확실하지 않습니다. 당신의 요점을 더 명확하게 만드는 코드 샘플을 보여줄 수 있습니까?
Rishabh

2
화면에 50 개 이상의 입력이있는 경우 상태 변경에 대해 각각 렌더링하는 것은 바람직하지 않습니다. 각 input필드가 자체 상태를 유지하는 각 필드를 구성하는 것이 이상적입니다. 어느 시점에서 우리는 이러한 다양한 독립 상태를 일부 더 큰 모델로 조정해야합니다. 어쩌면 우리는 타이머에 자동 저장을 할 수 있습니다. 아니면 그냥 저장합니다. componentWillUnmount이것이 내가 refs이상적 이라고 생각하는 곳입니다. 조정하는 동안 우리 state는 각각 의 값을 가져옵니다.ref 더 현명한 것은 없습니다. 나는 대부분의 경우에 동의하는 state대답이지만, 많은 수의 inputs적절한 활용 refs패턴을 성능 혜택입니다
럭셔리

105

나는 몇몇 사람들이 위의 대답을 "절대 심판을 사용하지 않는"이유로 인용하는 것을 보았고 나는 나의 (그리고 내가 이야기 한 몇몇 다른 React 개발자들에게도) 의견을주고 싶다.

구성 요소 인스턴스에 대해 사용하는 것에 대해 말할 때 "참조를 사용하지 마십시오"라는 정서는 정확합니다. 즉, 컴포넌트 인스턴스를 가져오고 이에 대한 메서드를 호출하는 방법으로 ref를 사용해서는 안됩니다. 이것은 refs를 사용하는 잘못된 방법이며 refs가 빠르게 남쪽으로 이동하는 경우입니다.

참조를 사용하는 올바른 (매우 유용한) 방법은 참조를 사용하여 DOM에서 값을 가져올 때입니다. 예를 들어 해당 입력에 참조를 첨부하는 입력 필드가있는 경우 나중에 참조를 통해 값을 잡는 것이 좋습니다. 이 방법이 없으면 입력 필드를 현지 주 또는 플럭스 스토어로 최신 상태로 유지하기 위해 상당히 조정 된 프로세스를 거쳐야합니다. 이는 불필요 해 보입니다.

2019 년 편집 : 미래의 친구들 안녕하세요. 내가 몇 년 전에 언급 한 것 외에도 ^, React Hooks를 사용하면 ref는 렌더링 사이에 데이터를 추적하는 좋은 방법이며 DOM 노드를 잡는 것에 국한되지 않습니다.


3
마지막 단락이 완벽하게 이해되지만 두 번째 단락을 명확히 할 수 있습니까? 구성 요소 인스턴스를 잡고 잘못된 것으로 간주되는 메서드를 호출하는 구체적인 예는 무엇입니까?
대니 Libin

2
나는 이것에 동의합니다. 필드 값의 유효성 검사 또는 조작이 필요하지 않는 한 / 때까지 ref를 사용합니다. 변경시 유효성을 검사하거나 프로그래밍 방식으로 값을 변경해야하는 경우 상태를 사용합니다.
Christopher Davies

1
나도 이것에 동의합니다. 발견 단계에서 의도적으로 순진한 입력이 많은 화면에 접근했습니다. ID로 키가 지정된 맵 (상태)에 저장된 모든 입력 값. 말할 필요도없이, 체크 박스 클릭과 같은 사소한 UI 변경에 대해 상태를 설정하고 50 개 이상의 입력 (무거운 재료 UI)을 렌더링하기 때문에 성능이 저하되었습니다. 자체 상태를 유지할 수있는 각 입력을 구성하는 것은 적절한 접근 방식으로 보였습니다. 조정이 필요한 경우을 refs살펴보고 상태 값을 가져옵니다. 실제로 정말 멋진 패턴 인 것 같습니다.
lux

2
완전히 동의 해. 내 의견으로는 받아 들여진 대답이 너무 모호합니다.
James Wright

나는 동의한다. 일반적인 Form 구성 요소를 설계하는 동안 제어 된 구성 요소와 관리 포커스, 오류 처리 등의 문제점을 해결합니다. 실제로 깨끗한 아키텍처를 가질 수 없습니다. 필요한 경우 저에게 말하십시오. 내 구성 요소를 심판으로 옮깁니다.
kushalvm

6

TL; DR 일반적으로 refsReact의 선언적 철학 에 위배 되므로 최후의 수단으로 사용해야합니다. state / props가능할 때마다 사용하십시오 .


어디 요 사용을 이해하기 위해 refs대를state / props , 반응하는 디자인 원칙의 일부에서 살펴 보자는 다음과 같습니다.

에 대한 React 문서refs

선언적으로 수행 할 수있는 모든 것에 refs를 사용하지 마십시오.

이스케이프 해치 에 대한 React의 설계 원칙

앱 빌드에 유용한 일부 패턴을 선언적 방식으로 표현하기 어려운 경우이를위한 명령형 API를 제공합니다. (그리고 그들은 여기에 심판에 연결됩니다)

즉, React의 팀 은 반응 적 / 선언적 방식으로 수행 할 수있는 모든 것을 피하고 refs사용하도록 제안합니다 state / props.

@Tyler McGinnis는 매우 좋은 답변 을 제공했습니다.

참조를 사용하는 올바른 (매우 유용한) 방법은 참조를 사용하여 DOM에서 값을 얻을 때입니다.

그렇게 할 수는 있지만 React의 철학에 반하게 될 것입니다. 입력에 가치가 있다면 가장 확실하게 state / props. 코드를 일관되고 예측 가능하게 유지하려면 state / props거기에도 충실해야 합니다. 나는 refs때때로 당신에게 더 빠른 해결책을 제공 한다는 사실을 인정합니다 . 그래서 당신이 개념 증명을한다면 빠르고 더럽습니다. 것은 받아 들일 수 있습니다.

이것은 우리에게 몇 가지 구체적인 사용 사례 를 남깁니다.refs

포커스, 텍스트 선택 또는 미디어 재생 관리. 명령형 애니메이션 트리거. 타사 DOM 라이브러리와 통합.


5

이 게시물은 오래되었습니다.

나는 그 문제에 대한 한 가지 사례에 대한 나의 작은 경험을 공유 할 것입니다.

저는 많은 '동적'입력과 많은 캐시 된 데이터가 포함 된 큰 구성 요소 (414 줄)를 작업하고있었습니다. (나는 페이지에서 혼자 작업하지 않으며, 내 감각은 코드의 구조가 아마도 더 잘 분리 될 수 있다고 말해 주지만, 요점은 아닙니다 (글쎄, 그럴 수 있지만 처리하고 있습니다)

먼저 상태와 함께 입력 값을 처리했습니다.

  const [inputsValues, setInputsValues] = useState([])
  const setInputValue = (id, value) => {
    const arr = [...inputsValues]
    arr[id] = value
    setInputsValues(arr)
  }

그리고 물론 입력 :

value={inputsValues[id] || ''}
onChange={event => setInputValue(id, event.target.value)}

렌더링이 너무 무거워서 입력 변경이 ****처럼 고르지 않았습니다 (키를 누르지 마십시오. 텍스트는 일시 중지 후에 만 ​​나타납니다)

나는 심판을 사용하여 이것을 피할 수 있다고 확신했습니다.

다음과 같이 끝났습니다.

  const inputsRef = useRef([])

그리고 입력에서 :

ref={input => (inputsRef.current[id] = input)}

[제 경우에는 Input이 Material-UI TextField 였으므로 다음과 같습니다.

inputRef={input => (inputsRef.current[id] = input)}

]

덕분에 다시 렌더링하지 않고 입력이 부드럽습니다. 이 동일한 방식으로 작동합니다. 주기와 계산이 절약되므로 에너지도 절약됩니다. 지구를 위해 해 x)

내 결론 : 입력 값에 대한 useRef가 필요할 수도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.