programing

setState를 호출하지 않고 React 컴포넌트를 강제로 다시 렌더링할 수 있습니까?

oldcodes 2023. 3. 25. 11:54
반응형

setState를 호출하지 않고 React 컴포넌트를 강제로 다시 렌더링할 수 있습니까?

변경 내용을 수신할 외부(컴포넌트에 대한) 관찰 가능한 개체가 있습니다.개체가 업데이트되면 변경 이벤트가 발생하며, 변경이 감지되면 구성 요소를 다시 렌더링하려고 합니다.

레벨의 with with with with with with withReact.render했지만, 은, 「로 말이 」라고 하는 이므로).render메서드

다음은 코드 예시입니다.

export default class MyComponent extends React.Component {

  handleButtonClick() {
    this.render();
  }

  render() {
    return (
      <div>
        {Math.random()}
        <button onClick={this.handleButtonClick.bind(this)}>
          Click me
        </button>
      </div>
    )
  }
}

으로 버튼을 하면 '내부'가 호출됩니다.this.render()이 되는 것은 이 되지 않는 것은 입니다).{Math.random()}변하지 않습니다).this.setState()this.render()정상적으로 동작합니다.

그래서질문은 리액트 컴포넌트가 재연성을 위해 상태를 가질 필요가 있는가 하는 것입니다.상태를 변경하지 않고 온 디맨드로 컴포넌트를 강제로 갱신할 수 있는 방법이 있습니까?

컴포넌트에서는, 「」를 호출할 수 .this.forceUpdate()강제로 리렌더로 만들었죠

문서: https://facebook.github.io/react/docs/component-api.html

성분에 forceUpdate단, 후크를 사용하여 강제로 업데이트를 수행할 수 있습니다.

forceUpdate리액트 사고방식에서 벗어나기 때문에 피해야 합니다.에서는 리액트할 때의 합니다.forceUpdate사용할 수 있습니다.

기본적으로 구성요소의 상태가 변경되면 구성요소가 다시 렌더링됩니다.단, 이러한 변경이 암묵적으로 이루어지는 경우(예를 들어 오브젝트 자체를 변경하지 않고 오브젝트 내의 데이터가 변경되는 경우) 또는 render() 메서드가 다른 데이터에 의존하는 경우 forceUpdate()를 호출하여 render()를 재실행해야 함을 React에 알릴 수 있습니다.

깊이 라도 하, however, however, , 는, 는, however, however, however, however, however, however, however, however, however, however, however, however, however, however, however, howeverforceUpdate불필요합니다.불변의 데이터 소스 트래킹을 사용하면 변경 비용이 절감됩니다.변경 시 항상 새로운 오브젝트가 생성되므로 오브젝트에 대한 참조가 변경되었는지 확인만 하면 됩니다.라이브러리 불변 JS를 사용하여 불변 데이터 개체를 앱에 구현할 수 있습니다.

일반적으로 forceUpdate()의 모든 사용을 피하고 render()의 this.props 및 this.state에서만 읽어야 합니다.이를 통해 컴포넌트는 "순수"하고 어플리케이션은 훨씬 심플하고 효율이 향상됩니다.force Update()

다시 렌더링할 요소의 키를 변경하면 작동합니다.상태를 통해 요소의 키 프로포트를 설정한 다음 설정 상태를 업데이트하여 새 키를 갖게 합니다.

<Element key={this.state.key} /> 

그런 다음 변경이 발생하여 키를 리셋합니다.

this.setState({ key: Math.random() });

이것은 키를 변경하는 요소를 대체하는 것입니다.예를 들어 이미지 업로드 후 리셋할 파일 입력 필드가 있는 경우 등이 도움이 됩니다.

에 대한 입니다.forceUpdate()이 솔루션은 다양한 상황에서 도움이 됩니다., 만약 이 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.forceUpdate코드를 검토하여 다른 방법이 있는지 알아보는 것이 좋습니다.

참고 1-9-2019:

위의 (키를 변경하면) 요소가 완전히 교체됩니다.변경하기 위해 키를 갱신하고 있는 경우는, 코드의 다른 장소에 문제가 있는 경우가 있습니다.「」를 사용합니다.Math.random()키를 누르면 각 렌더링으로 요소가 다시 생성됩니다.리액션은 키를 사용하여 재렌더하는 최선의 방법을 결정하기 때문에 이러한 키 업데이트는 권장하지 않습니다.

2021년과 2022년에는 이것이 React 기능 컴포넌트를 강제 갱신하는 공식 방법입니다.

const [, forceUpdate] = useReducer(x => x + 1, 0);

  function handleClick() {
    forceUpdate();
  }

OP op op op op op op op op op op op op 。 이 질문은 되었고, 수 있게 되었기 이 are년년년년년년년년 for for for for for for for for for for for for for 를 검색할 수 있다.forceUpdate기능 컴포넌트에 포함되어 있습니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★

2022년 4월 18일 편집

컴포넌트를 강제로 갱신하는 것은 보통 잘못된 방법입니다.

강제 업데이트를 사용해야 하는 몇 가지 이유가 있습니다.

  • 로컬, 리덕스, 컨텍스트와 같은 상태 변수를 사용하지 않습니다.
  • 액세스하려는 상태 개체의 필드가 개체 또는 배열에 너무 깊게 중첩되어 있습니다.Redux도 평면 객체 또는 어레이를 유지하도록 권장하고 있습니다.복잡한 개체에서 필드 값이 하나만 변경되는 경우 React는 상태 개체가 변경되었음을 인식하지 못할 수 있으므로 구성 요소를 업데이트하지 않습니다.상태를 단순하고 평평하게 유지하십시오.
  • 다른 답변에서 언급한 것처럼 목록 항목의 키입니다.사실, 이것은 다른 예상치 못한 행동도 일으킬 수 있다.키가 동일하지 않거나 키가 모두 없어 항목이 반복적으로 렌더링(복제)되는 목록을 보았습니다.항상 백엔드 팀에 원하는 ID를 전송하도록 요청하십시오.키에 어레이 인덱스를 사용하지 않도록 합니다.프런트 엔드에서 nanoid, uuid 또는 random을 사용하여 하나의 ID를 생성하려고 하지 마십시오.위의 방법을 사용하여 작성된 ID는 컴포넌트가 갱신될 때마다 변경되기 때문에(목록에 제공된 키는 정적이고 각 렌더에서 동일해야 합니다).고유 ID의 작성은 보통 백엔드의 문제입니다.그 요건을 전면에 내세우지 않도록 최선을 다하세요.프런트 엔드의 책임은 백엔드가 반환하는 데이터를 그리는 것일 뿐 데이터를 즉시 생성하는 것은 아닙니다.
  • useEffect의 경우 useCallback 의존관계 배열에 적절한 값이 설정되어 있지 않습니다.ESLint를 사용하여 지원하세요!또한 이는 React 메모리 누수의 가장 큰 원인 중 하나입니다.메모리 누수를 방지하기 위해 리턴 콜백에서 상태 및 이벤트청취자를 청소합니다.이러한 메모리 누수는 디버깅이 매우 어렵기 때문입니다.
  • 콘솔을 항상 감시하십시오.직장에서 가장 친한 친구잖아콘솔에 표시되는 경고와 오류를 해결하면 버그나 자신도 모르는 문제 등 많은 문제를 해결할 수 있습니다.

내가 잘못했다는 걸 기억할 수 있는 게 몇 가지 있어.혹시 도움이 될까봐..

로로 actually actually actually actually.forceUpdate() is is is is is 、 is is 、 is is as as as as 。setState()추가 로직이 실장되어 있는 경우 재실행은 트리거되지 않을 수 있습니다.shouldComponentUpdate() 반환되는 false.

force Update()

" "forceUpdate()이 되다render()shouldComponentUpdate()더...

setState()

setState()는 조건부 되지 않는 한 항상 .shouldComponentUpdate()더...


forceUpdate() can be called from within your component by this.forceUpdate()


Hooks: React에서 Hooks를 사용하여 컴포넌트를 강제로 다시 렌더링하려면 어떻게 해야 합니까?


BTW: 상태를 변환하시겠습니까, 아니면 중첩된 속성이 전파되지 않습니까?

forceUpdate

잘못된 방법: 인덱스를 키로 사용하지 마십시오.

this.state.rows.map((item, index) =>
   <MyComponent cell={item} key={index} />
)

올바른 방법: 데이터 ID를 키로 사용합니다. GUID일 수 있습니다.

this.state.rows.map((item) =>
   <MyComponent item={item} key={item.id} />
)

따라서 이러한 코드 개선을 통해 컴포넌트는 고유하고 자연스럽게 렌더링됩니다.

관계(부모-자녀)에 구속되지 않는 두 개의 React 구성 요소가 통신하도록 하려면 플럭스 또는 유사한 아키텍처를 사용하는 것이 좋습니다.

당신이 하고 싶은 것은 그 변경에 귀를 기울이는 것이다. 관측 가능한 성분 store: 모델과 해당 인터페이스를 유지하고 렌더를 변경하는 데이터를 다음과 같이 저장합니다.stateMyComponent스토어에서 새 데이터를 푸시하면 컴포넌트 상태가 변경되어 렌더가 자동으로 트리거됩니다.

에는 사용하지 .forceUpdate() 다음 중 하나:

일반적으로 forceUpdate()의 모든 사용을 피하고 render()의 this.props 및 this.state에서만 읽어야 합니다.이것에 의해, 애플리케이션의 심플화와 효율이 향상됩니다.

후크 또는 HOC 사용 선택

후크 또는 HOC(고차 컴포넌트) 패턴사용하여 스토어가 변경될 때 자동 업데이트를 수행할 수 있습니다.이것은 프레임워크가 없는 매우 가벼운 접근법입니다.

스토어 업데이트를 처리하는 useStore Hooks 방법

interface ISimpleStore {
  on: (ev: string, fn: () => void) => void;
  off: (ev: string, fn: () => void) => void;
}

export default function useStore<T extends ISimpleStore>(store: T) {
  const [storeState, setStoreState] = useState({store});
  useEffect(() => {
    const onChange = () => {
      setStoreState({store});
    }
    store.on('change', onChange);
    return () => {
      store.off('change', onChange);
    }
  }, []);
  return storeState.store;
}

withStores HOC 스토어 업데이트 처리

export default function (...stores: SimpleStore[]) {
  return function (WrappedComponent: React.ComponentType<any>) {
    return class WithStore extends PureComponent<{}, {lastUpdated: number}> {
      constructor(props: React.ComponentProps<any>) {
        super(props);
        this.state = {
          lastUpdated: Date.now(),
        };
        this.stores = stores;
      }

      private stores?: SimpleStore[];

      private onChange = () => {
        this.setState({lastUpdated: Date.now()});
      };

      componentDidMount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            // each store has a common change event to subscribe to
            store.on('change', this.onChange);
          });
      };

      componentWillUnmount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            store.off('change', this.onChange);
          });
      };

      render() {
        return (
          <WrappedComponent
            lastUpdated={this.state.lastUpdated}
            {...this.props}
          />
        );
      }
    };
  };
}

Simple Store 클래스

import AsyncStorage from '@react-native-community/async-storage';
import ee, {Emitter} from 'event-emitter';

interface SimpleStoreArgs {
  key?: string;
  defaultState?: {[key: string]: any};
}

export default class SimpleStore {
  constructor({key, defaultState}: SimpleStoreArgs) {
    if (key) {
      this.key = key;
      // hydrate here if you want w/ localState or AsyncStorage
    }
    if (defaultState) {
      this._state = {...defaultState, loaded: false};
    } else {
      this._state = {loaded: true};
    }
  }
  protected key: string = '';
  protected _state: {[key: string]: any} = {};
  protected eventEmitter: Emitter = ee({});
  public setState(newState: {[key: string]: any}) {
    this._state = {...this._state, ...newState};
    this.eventEmitter.emit('change');
    if (this.key) {
      // store on client w/ localState or AsyncStorage
    }
  }
  public get state() {
    return this._state;
  }
  public on(ev: string, fn:() => void) {
    this.eventEmitter.on(ev, fn);
  }
  public off(ev: string, fn:() => void) {
    this.eventEmitter.off(ev, fn);
  }
  public get loaded(): boolean {
    return !!this._state.loaded;
  }
}

사용방법

후크의 경우:

// use inside function like so
const someState = useStore(myStore);
someState.myProp = 'something';

HOC의 경우:

// inside your code get/set your store and stuff just updates
const val = myStore.myProp;
myOtherStore.myProp = 'something';
// return your wrapped component like so
export default withStores(myStore)(MyComponent);

매장을 싱글톤으로 수출하여 다음과 같은 글로벌 변화의 혜택을 누리십시오.

class MyStore extends SimpleStore {
  public get someProp() {
    return this._state.someProp || '';
  }
  public set someProp(value: string) {
    this.setState({...this._state, someProp: value});
  }
}
// this is a singleton
const myStore = new MyStore();
export {myStore};

이 접근방식은 매우 간단하고 나에게도 효과가 있습니다.저도 큰 팀으로 일하는데 Redux와 MobX를 사용하고 있는데 그것도 좋지만 그냥 보일러 플레이트가 많아요.저는 개인적으로 저만의 방식을 좋아합니다. 왜냐하면 저는 항상 필요할 때 간단한 것에 대한 많은 코드를 싫어했기 때문입니다.

그래서 제 질문은 리액트 컴포넌트가 재연성을 위해 상태를 가질 필요가 있는가 하는 것입니다.상태를 변경하지 않고 온 디맨드로 컴포넌트를 강제로 갱신할 수 있는 방법이 있습니까?

다른 답변들은 어떻게 할 수 있는지 설명하려고 노력했지만, 요점은 그렇게 하지 말아야 한다는 것입니다.심지어 키를 바꾸는 진부한 해결책도 요점을 놓쳤다.React의 힘은 렌더링해야 할 시기를 수동으로 관리하는 것을 포기하고 입력에 매핑하는 방법을 고민하는 것입니다.그런 다음 입력 스트림을 공급합니다.

수동으로 재렌더를 강제해야 하는 경우, 제대로 된 작업을 하고 있지 않은 것이 거의 확실합니다.

컴포넌트를 재렌더하는 방법에는 몇 가지가 있습니다.

가장 간단한 해결책은 forceUpdate() 메서드를 사용하는 것입니다.

this.forceUpdate()

또 하나의 해결책은 스테이트(nonUsedKey)에 미사용 키를 생성하여 이 nonUsedKey를 갱신하여 setState 함수를 호출하는 것입니다.

this.setState({ nonUsedKey: Date.now() } );

또는 모든 현재 상태를 다시 씁니다.

this.setState(this.state);

소품 교환은 컴포넌트 렌더도 제공합니다.

완전성을 위해 기능 컴포넌트에서도 이를 실현할 수 있습니다.

const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
// ...
forceUpdate();

또는 재사용 가능한 후크로서:

const useForceUpdate = () => {
  const [, updateState] = useState();
  return useCallback(() => updateState({}), []);
}
// const forceUpdate = useForceUpdate();

참조: https://stackoverflow.com/a/53215514/2692307

강제 갱신 메커니즘을 사용하는 것은 반응 정신에 반하기 때문에 여전히 나쁜 관행이므로 가능하면 피해야 한다는 점에 주의하시기 바랍니다.

몇 가지 방법으로 할 수 있습니다.

. 1. 지만하다를 하세요.forceUpdate()★★★★

경우 할 수 .forceUpdate(), '무시하다', '무시하다', '무시하다'.shouldComponentUpdate()메서드 및 뷰 재인스톨을 실시합니다.shouldComponentUpdate()거짓으로 속이다forceUpdate()는 forceUpdate()로 지정합니다.

this를 2. 에 합니다.setState()

다음 코드 행은 위의 예에서 문제를 해결합니다.

this.setState(this.state);

실제로는 현재 상태를 현재 상태로 덮어쓰기하여 재렌더링을 트리거합니다.이것이 반드시 최선의 방법은 아니지만 forceUpdate() 메서드를 사용하여 발생할 수 있는 몇 가지 결함을 극복합니다.

이거 쓸 수 있어.forceUpdate()는 다음과 같습니다.

       class MyComponent extends React.Component {



      handleButtonClick = ()=>{
          this.forceUpdate();
     }


 render() {

   return (
     <div>
      {Math.random()}
        <button  onClick={this.handleButtonClick}>
        Click me
        </button>
     </div>
    )
  }
}

 ReactDOM.render(<MyComponent /> , mountNode);

DOM의 요소 'Math.random' 부분은 setState를 사용하여 컴포넌트를 다시 렌더링해도 갱신됩니다.

여기 있는 모든 답변은 이해를 위한 질문을 보완하는 올바른 답변입니다.setState({})를 사용하여 컴포넌트를 out으로 리렌더하는 경우는 forceUpdate()를 사용합니다.

위의 코드는 다음과 같이 setState에서 실행됩니다.

 class MyComponent extends React.Component {



             handleButtonClick = ()=>{
                this.setState({ });
              }


        render() {
         return (
  <div>
    {Math.random()}
    <button  onClick={this.handleButtonClick}>
      Click me
    </button>
  </div>
)
  }
 }

ReactDOM.render(<MyComponent /> , mountNode);

승인된 답변을 백업하기 위한 다른 답변:-)

으로 인해 을 할 수 있습니다.forceUpdate()기능 프로그래밍에 대해 일반적으로 "이것이 유일한 방법"이라는 접근방식을 가지고 있기 때문입니다.이것은 대부분의 경우 괜찮지만, 많은 리액트 개발자들은 OO 배경을 가지고 있으며, 그러한 접근 방식이라면 관찰 가능한 물체를 듣는 것은 완벽하게 괜찮다.

만약 한다면,한 "발화를 할 때 한다는 것을 있을 은 "발화"하다, "발화"하다, "발화"하다를 해야 합니다. 그리고 그렇게 해서, 당신은 사용해야 한다.forceUpdate()'아까부터'는 입니다.shouldComponentUpdate()는 여기에 관여하지 않습니다.

MobX와이를 는 MobX를 MobX로 호출합니다).render()□□□□□□□□★

forceUpdate()는 다른 사람이 그것에 대해 말하는 것을 들을 때마다 이것을 사용하지 않는 것이 좋습니다.

forceUpdate();하지만, 사용하시는 .setState();

당신이 설명하는 것을 실현하기 위해 이것을 시도해 보세요.forceUpdate()를 선택합니다.

은 '하다'라고 부르는 입니다.setState상태 유지:

this.setState(prevState=>({...prevState}));

force Update()를 피하는 것이 가장 좋습니다.강제로 재렌더를 수행하는 한 가지 방법은 임시 외부 변수에 render() 종속성을 추가하고 필요에 따라 해당 변수의 값을 변경하는 것입니다.

다음은 코드 예시입니다.

class Example extends Component{
   constructor(props){
      this.state = {temp:0};

      this.forceChange = this.forceChange.bind(this);
   }

   forceChange(){
      this.setState(prevState => ({
          temp: prevState.temp++
      })); 
   }

   render(){
      return(
         <div>{this.state.temp &&
             <div>
                  ... add code here ...
             </div>}
         </div>
      )
   }
}

이걸 불러주세요.force Change()를 지정합니다.

ES6 - 예를 들어 설명하겠습니다.이것은 다음과 같습니다.

"short if statement"에서는 다음과 같이 빈 함수를 전달할 수 있습니다.

isReady ? ()=>{} : onClick

이것이 가장 빠른 방법인 것 같다.

()=>{}

useEffectcomponentDidMount,componentDidUpdate , , , , 입니다.componentWillUnmount(리액션합니다).

componentDidMount는 이렇게 설정해야 합니다.

  useEffect(() => console.log('mounted'), []);

첫 번째 인수는 값 배열인두 번째 인수에 따라 실행되는 콜백입니다.의 값되었을 경우 되어 있습니다.useEffect고됩니니다다

단, 이 예에서는 빈 어레이를 두 번째 인수로 전달하고 있으며, 이는 변경되지 않으므로 컴포넌트가 마운트될 때 콜백 함수가 한 번 호출됩니다.

게 정리되어 있어요.useEffect. 다음과 다음과 같이 입력합니다.

 useEffect(() => {

  }, [props.lang]);

frops.변경될 됩니다.useEffect콜백 함수 내에서 재실행 가능성이 있는 상태를 관리하고 있지 않는 한 컴포넌트는 실제로 재실행되지 않습니다.

는, 「 」의 상태가 「 」로 되어 있을 .useEffect.

예를 들어 여기서 렌더링 함수는 영어를 기본언어로 표시하는 것으로 시작되며, 3초 후에 해당 언어를 변경하므로 렌더가 다시 렌더링되어 "스페인어"로 표시되기 시작합니다.

function App() {
  const [lang, setLang] = useState("english");

  useEffect(() => {
    setTimeout(() => {
      setLang("spanish");
    }, 3000);
  }, []);

  return (
    <div className="App">
      <h1>Lang:</h1>
      <p>{lang}</p>
    </div>
  );
}

자세한 체크는 forceUpdate()를 사용할 수 있습니다(forceUpdate()).

언급URL : https://stackoverflow.com/questions/30626030/can-you-force-a-react-component-to-rerender-without-calling-setstate

반응형