React에서 검색 키워드 필터 입력을 좋게 생각했습니다.

8730 단어 material-uiReactredux

소개



제목대로 React에서 Input 필드에 전각 입력되었을 때 깨끗이 움직이지 않았기 때문에 IME 대응 메모입니다.

싹둑 환경은 이런 느낌입니다.


도서관
버전


React
^16.10.2

Material-UI
^3.8.3

react-redux
^6.0.0


사양은 아래의 UML 그림과 같이,
  • 입력 필드에 입력
  • 입력 필드에 입력 한 내용으로 API 요청
  • API 응답을 store에 저장
  • store에서 props로 전달 렌더링

  • 어려움 그 1 전각 입력 문제 Material-UI의 Input API, onChange 를 사용하여 매번 API에 fetch 가는데, 전각 입력의 경우 "테스트"를 입력하면 "t, te, te s, teth, teth t, test ..."모두에서 fetch됩니다. . 입력 속도에 따라서는 「테스트」라고 입력하고 있습니다만, '테스 t'와 같은 입력이 확정 이전 상태에서 fetch한 정보가 store에 저장되어 버리는 문제가 발생했습니다. (어째서--.) 화면상에서는, 「테스트」로 검색 걸고 있을 생각이, 받고 있는 데이터는 「테스 t」로 리퀘스트한 데이터가 되어 있어 이상하다. . . 프론트에서만 필터링하여 대응할 수 있으면 좋았지만 사양 관계로 API를 요청할 필요가 있습니다. . (기술적인 부채를 고려한 UI라든지, 아무튼, 여러가지 문제는 여기에서는 두어 두어,) 그 2 프론트가 무겁다. Input 필드가 변경될 때마다 onChange가 실행되므로 API 요청이 여러 번 실행됩니다. 중복 된 다중 요청에 프론트 측 입력의 거동도 걸려 버려서 좋지 않습니다 ... 이런, 「좋은 느낌」으로 하기 위한 수수한 곳은 상당히 힘들 때 많습니다. 원래 불필요한 요청을 제한할 수 있으면 이상. . . 해결 방법 1 전각 입력 중에는 API를 요청하지 않습니다. onCompositionStart & onCompositionEnd 메서드를 활용하여 회피했습니다. 원인으로서는, 입력 미확정 상태로 리퀘스트 던져(게다가 몇번이나) 버리는 것이었던 것입니다. 전각 입력 개시시에 onCompositionStart 메소드는 발화, 전악 입력 확정시에 onCompositionEnd 메소드가 발화해 주는 것 같습니다. Material-UI의 공식 문서에 준비되어 있는 메소드가 아니라, Input 태그가 가지는 이벤트의 React 버젼으로서 준비되어 있는 것 같습니다. 참조: 공식 React 참조(composition events)

    구체적인 해결 방법


    onChange 메소드로 전각 입력중인가 어떤가의 state 치를 봐, false 의 경우만 fetch 하도록 변경
    반각 입력에는 특별히 제한이 없으므로, 반각 입력시의 다중 요구는 회피할 수 없습니다. . . 울다
    
    onChange = ({ target: { value: keyword }) => {
      this.setState({ keyword }, () => {
        if(!this.state.isIME) {
          this.props.fetchthis.state.keyword
        }
      }) 
    }
    onCompositionStart = () => {
      this.setState({ isIME: true })
    }
    onCompositionEnd = () => {
      this.setState({ isIME: false }})
    }
    
    ...
    <Input
      name="keyword"
      type="text"
      onChange={this.onChange}
      onCompositionStart={this.onCompositionStart}
      onCompositionEnd={this.onCompositionEnd}
      value={this.state.keyword}
    >
    ...
    

    이것으로 어떻게든 이상의 동작은 확인할 수 있었습니다.

    그 2 입력을 좋은 느낌으로 취득하여 다중 요청을 회피


    setTimeout() 를 사용하여 API 요청을 수행했습니다.onChange 가 달린 타이밍에, 입력중이라고 하는 스테이터스를 관리하는 state 를 생성.
    setTImeout(fetch, 800) 와, 0.8 초등 적당한 간격으로, fetch 시키도록 합니다.
    (0.8초 이내의 재요청은 아직 입력 중이라고 판단시킨다)
    다중 요청을 피하기 위해 onChange 발화 터밍 중에 타이머를 재설정하여 피했습니다.

    이제 0.8초 이내에 새 요청이 발생하는 경우에도 마지막 요청을 중지합니다.

    구체적인 해결 방법



    이제 0.8초 이내의 텍스트 입력 시 API 요청 없이 쓸데없는 처리도 실행하지 않습니다.
    프런트도 조금 가볍게 할 수 있었다.
    onChange = ({ target: { value: keyword } }) => {
        clearTimeout(this.timer)
        this.setState(
          {
            isChange: true,
            keyword,
          },
          () => {
            this.timer = setTimeout(() => {
              this.setFilterState()
            }, 800)
          },
        )
      }
    
    ...
    <Input
      name="keyword"
      type="text"
      onChange={this.onChange}
      value={this.state.keyword}
    >
    ...
    

    사이고에게



    처리 무겁고 상당히 유저에게 있어서, 미움받는 비율 높기 때문에(자신도 싫음), 개발자로서 가벼운 동작이거나, 매끄러운 인터랙션이라고 하는 것은 신경써 가고 싶다고 생각합니다.setTImeout() 어쨌든 상당히 시원하지 않은 느낌의 메소드라는 인상이 강해서, 그다지 사용하고 싶지 않습니다만, 이번은 상당히 좋은 사용법 할 수 있었던 것은? 라고 마음대로 생각합니다.

    그 밖에 더 좋은 방법 있다든가, 원래 안 되겠다는 곳도 있을지도라, 그런 코멘트라든지 받을 수 있으면 감사입니다. . .

    뱀발



    React 하고 있으면, componentDidUpdata 라든지, 루프와 같이 처리 달리 버리는 것이 자주 있는 것입니다만, 하는 방법 없는 것일까. . .
    이 변 예쁘게 걸도록 설계 반죽 반죽해야 하는 것일까....

    React 처음 곧 1년 정도 지나지만, 아직 익숙하지 않고 어려울 거라고 생각합니다.
    (Hooks도 하지 않으면, redux 졸업하지 않으면...)

    좋은 웹페이지 즐겨찾기