• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    미해결

mobx state action 변화 감지 관련

22.09.19 11:01 작성 조회수 503

0

안녕하세요. mobx 강의 관련 친절하고 쉬운 설명 감사합니다.

제가 질문할려는 것은 강의에서는 언급하지는 않았지만, reaction과 거의 유사한 mobx 함수인 autorun에 대해 여쭤볼게 있어 질문 올립니다.

reaction은 감지할 state를 언급하면 그 state에 따라만 언급하는 걸로 알고 있고,

autorun은 모든 observable state에 대해 반응 하는 걸로 제가 알고 있는데요..

var renderCount = 1;  
const App = observer (()  => {

  const [object, setObject] =useState({name :' inha', id: 0})
  //const [renderCount, setRenderCount] = useState(0);
  
  const test_state = useLocalObservable(()=>({
    name : '',
    id : 0,
    
  }))

  function handle_Click() {

    renderCount++;
    test_state.id++;

    mobx_store.setarr(renderCount);

  }

 autorun(()=>{
    console.log('autorun')
  })

  useEffect ( ()=>{
    reaction(()=>{ 
      return test_state.id
    },()=>{
      console.log('test_atate_reaction')
    })
  },[])
  

해당 코드에서 보시면 autorun과 reaction을 호출 등록하였고, reaction에 대해 test_state.id에 반응 하도록 했습니다. 실행을 하고 click 이벤트를 진행하면 reaction에 있는 console은 찍히지만, autorun에 있는 console은 제일 처음 실행 했을 때 말고는 찍히지가 않아여.

return (//useObserver hook 나 Observer  감싸줘야 react에서 mobx가 제대로 적용 가능 
    <div >
      <p>
        current render count : {renderCount}
      </p>

      <button onClick={() => handle_Click()}>
        Click
      </button>
    </div>
  );

그리고 해당 return문에 observable로 감싼 state가 따로 쓰이지 않으면 렌더링도 새로 되지 않아요.ㅠㅠ

만약에 return문에 observable로 감싼 state가 있으면 리렌더링이 되고, 그때는 autorun도 호출됩니다.( 아마 렌더링 시에 자동으로 호출되서 그런것 같아요. 이건)

혹시 정확한 이유를 알 수 있을까요??

autorun 같은 경우에는 꼭 observale로 감싼 것이 아닌 usestate로 선언한 state의 action에 의해 렌더링이 되도 호출 됩니다.

 

 

답변 1

답변을 작성해보세요.

0

autorun을 useEffect 안에 넣어보시겠어요? 지금 위치에서는 리렌더링될 때 autorun이 계속 호출됩니다.

useEffect(()=>
    autorun(()=>{ 
      console.log('autorun')
    })
  )

네 이런식으로 도 진행 보았고, dependecy를 [] <- 이렇게 도 넣어서 진행 해보았습니당. 하지만 질문에서 언급한 것처럼 return문에 observable로 감싼 state가 없으면 리렌더링이 되지 않아서 호출 되지는 않습니다.

그리고 return문에 observable로 감싼 state를 사용하지 않으면, state가 변경해도 렌더링은 안되는 것이 맞나여?? 위 코드에서 보시면 click 했을때 rendercount는 증가하도록 했는데, state를 사용하지 않아서 click event에서 state action을 진행해도, reaction은 호출이 되는데, 렌더링은 되지 않아서여 ㅠㅠ

 

리액트는 무조건 state가 변경되면 리렌더링됩니다. observable로 감싼 state는 mobx state를 react가 인식하도록 만드는 것이고요. 말씀하신 renderCount는 useState도 아니고 useLocalObservable도 아닌 그냥 변수입니다. 이걸 수정하는 것은 당연히 리렌더링이 안 되죠.

제가 예시를 잘못 드려 혼동 된거 같습니다.. 죄송합니다. 제가 하고 싶은 말은

const App = (() => {

  const [value, setValue] = useState(0);
  function handle_Click() {

      setValue(value => value+1)
  }

  useEffect(() => { //렌더링이 진행될 때 
    console.log('Rendering')
  })

  return (//useObserver hook 나 Observer  감싸줘야 react에서 mobx가 제대로 적용 가능 
    <div >

      <button onClick={() => handle_Click()}>
        Click
      </button>
    </div>
  );
}
)

image

위 코드에서 return문에 보시면 useState로 선언한 value를 굳이 return에 사용하지 않아도, click을 할 시 이벤트에서 setValue가 호출되면서 state값의 변화를 감지하고 리렌더링이 진행되는 것을 useEffect를 통해 알 수 있는데요.

const App = observer(() => {

  const test_state = useLocalObservable(() => ({
    name: '',
    id: 0,

    add() {
      this.id = ++this.id;
    }
  }))

  function handle_Click() {

    test_state.add();
  }

  useEffect(() => {
    reaction(() => {
      return test_state.id
    }, () => {
      test++;
      console.log('test_state')
    })
  },[])

  useEffect(() => { //렌더링이 진행될 때 
    console.log('Rendering')
  })

  return (//useObserver hook 나 Observer  감싸줘야 react에서 mobx가 제대로 적용 가능 
    <div >

      <button onClick={() => handle_Click()}>
        Click
      </button>
    </div>
  );
}
)
export default App;

mobx state 같은 경우에는 return 문에 mobx state가 없으면 useEffect가 발생되지 않아여ㅠㅠ. useEffect가 발생되지 않는 다는 것은 렌더링은 진행되지 않았다고 생각하고 있어서 질문드립니다.

물론 reaction을 통한 mobx state 변화는 감지를 합니다.

이미지도 같이 첨부 드립니다. 첫번째 사진은 return문에 mobx state 를 사용하지 않았을 경우, 두번쨰 사진은 return문에 mobx state를 사용했을 경우입니다. 두번 째 사진을 보시면 useEffect에 console이 호출 되는 것을 확인 할 수 있읍니다.

imageimage

여러 번 질문 드려서 죄송합니다.

 

이건 저도 처음 안 사실이네요. setState(다른값)를 하면 무조건 리렌더링되는 것은 맞습니다. useLocalObservable은 return 안에서 사용하지 않으면 리렌더링이 안 되나보네요.몹엑스 안 쓴지 2년이 넘어서 저도 기억이 잘 안 납니다.