programing

기능 구성요소에 상태 변수가 아닌 변수 저장

yellowcard 2023. 3. 11. 08:48
반응형

기능 구성요소에 상태 변수가 아닌 변수 저장

다음은 거의 동일한 기능을 하는 2개의 리액트 컴포넌트입니다.하나는 함수이고 다른 하나는 클래스입니다.각 컴포넌트에는Animated.Value갱신하는 비동기 청취자_foo거스름돈으로액세스 할 수 있어야 합니다._foo기능적인 컴포넌트에서는this._foo고전적인 구성 요소에서.

  • FunctionalBar하지 말았어야 했다_foo둘 이상의 경우에 대비하여 글로벌 범위 내에서FunctionalBar.
  • FunctionalBar가질 수 없다_foo기능 범위 내에 있습니다._foo재초기화 됩니다.FunctionalBar렌더링합니다. _foo또한 컴포넌트가 렌더링할 필요가 없기 때문에 상태가 되어서는 안 됩니다._foo변화들.
  • ClassBar이 문제는 없습니다.왜냐하면,_foo에 초기화된this컴포넌트의 전체 라이프 사이클에 걸쳐 있습니다.

어떻게 유지하지?_foo생애를 통해 초기화된FunctionalBar글로벌 범위에 넣지 않고요?

기능적 구현

import React from 'react';
import { Animated, View } from 'react-native';

var _foo = 0;

function FunctionalBar(props) {

  const foo = new Animated.Value(0);

  _onChangeFoo({ value }) {
    _foo = value;
  }

  function showFoo() {
    let anim = Animated.timing(foo, { toValue: 1, duration: 1000, useNativeDriver: true });
    anim.start(() => console.log(_foo));
  }

  useEffect(() => {
    foo.addListener(_onChangeFoo);
    showFoo();
    return () => foo.removeListener(_onChangeFoo);   
  });

  return <View />;

}

기존 구현

import React from 'react';
import { Animated, View } from 'react-native';

class ClassBar extends React.Component {

  constructor(props) {
    super(props);
    this.state = { foo: new Animated.Value(0) };
    this._foo = 0;
    this._onChangeFoo = this._onChangeFoo.bind(this);
  }

  componentDidMount() {
    this.state.foo.addListener(this._onChangeFoo);
    this.showFoo();
  }

  componentWillUnmount() {
    this.state.foo.removeListener(this._onChangeFoo);
  }

  showFoo() {
    let anim = Animated.timing(this.state.foo, { toValue: 1, duration: 1000, useNativeDriver: true });
    anim.start(() => console.log(this._foo));
  }

  _onChangeFoo({ value }) {
    this._foo = value;
  }

  render() {
    return <View />;
  }

}

훅은 DOM 참조 전용이 아니라 원하는 모든 가변 값을 저장할 수 있습니다.

function FunctionalBar(props) {
  const [foo] = useState(new Animated.Value(0));
  const _foo = useRef(0);

  function showFoo() {
    let anim = Animated.timing(foo, { toValue: 1, duration: 1000, useNativeDriver: true });
    anim.start(() => console.log(_foo.current));
  }

  useEffect(() => {
    function _onChangeFoo({ value }) {
      _foo.current = value;
    }

    foo.addListener(_onChangeFoo);
    showFoo();
    return () => foo.removeListener(_onChangeFoo);
  }, []);

  return <View />;
}

useRef 훅을 사용할 수 있습니다(이것은 문서에 기재되어 있는 권장 방법입니다).

  • 변수 선언:const a = useRef(5) // 5 is initial value
  • 값을 가져옵니다.a.current
  • 값 설정:a.current = my_value

Tholle의 답변을 뒷받침하기 위해 여기에 공식 문서가 있습니다.

언급

하지만,useRef()는 ref 속성보다 더 유용합니다.이 기능은 클래스에서 인스턴스 필드를 사용하는 방법과 유사한 모든 가변 값을 유지하는 데 유용합니다.

이것은, 다음과 같은 이유로 동작합니다.useRef()는 플레인 JavaScript 개체를 만듭니다.의 유일한 차이점은useRef()및 작성{current: ...}이의를 제기하다useRef는 모든 렌더에서 동일한 참조 객체를 제공합니다.

주의해 주세요useRef내용이 변경되어도 알리지 않습니다..current 속성을 변환해도 재렌더는 발생하지 않습니다.React가 참조를 DOM 노드에 연결하거나 분리할 때 일부 코드를 실행할 경우 대신 콜백 참조를 사용할 수 있습니다.

나는 파괴(+ 옵션 변수 별칭 "my")와 함께 후크를 사용하여 운이 좋았습니다. 그러면 당신은 당신의 모든 값을 "my"에 유지합니다.my여러 참조를 사용하거나 계속 사용할 필요가 없도록 객체 지정myref.current항상:

function MyComponent(props) {
  const componentRef = useRef({});
  const { current: my } = componentRef;

  my.count = 42;
  console.log(my.count); // 42

  my.greet = "hello";
  console.log(my.greet); // hello

  return <div />;
}

이것은 매우 드문 예이지만, 내가 올바르게 읽고 있다면, 당신은 단지 독특한 것을 저장하기를 원할 뿐입니다._foo또한 이 값이 변경되면 추가 렌더링을 방지할 수 있습니다.

이 시나리오는 이미 경험한 적이 있습니다.단순한 오브젝트(맵/해시)는 다음과 같은 처리를 합니다.

let foos = {}
let fooCount = 0

function F(props) {
  useEffect(() => {
    let fooId = fooCount++
    foos[fooId] = new Animated.Value(0)
    foos[fooId].addListener(...)
    return () => foos[fooId].removeListener(...)
  }, []) // <-- do not rerun when called again (only when unmounted)

  ...render...
}

그런 취지의 무언가를요실행 가능한 예제가 있는 경우 예제에 맞게 조정할 수 있습니다.어느 쪽이든 스코프 문제가 있는 대부분의 문제는 프리미티브로 해결됩니다.

언급URL : https://stackoverflow.com/questions/53146575/storing-non-state-variables-in-functional-components

반응형