1

I have this code.

and here is the code snippet

  const [indicators, setIndicators] = useState([]);
  const [curText, setCurText] = useState('');
  const refIndicator = useRef()

  useEffect(() => {
    console.log(indicators)
  }, [indicators]);

  const onSubmit = (e) => {
    e.preventDefault();
    setIndicators([...indicators, curText]);
    setCurText('')
  }

  const onChange = (e) => {
    setCurText(e.target.value);
  }


  const MemoInput = memo((props)=>{
    console.log(props)
    return(
      <ShowIndicator name={props.name}/>
    )
  },(prev, next) => console.log('prev',prev, next)
  );

It shows every indicator every time I add in the form.

The problem is that ShowIndicator updates every time I add something.

Is there a way for me to limit the the time my App renders because for example I created 3 ShowIndicators, then it will also render 3 times which I think very costly in the long run.

I'm also thinking of using useRef just to not make my App renders every time I input new text, but I'm not sure if it's the right implementation because most documentations recommend using controlled components by using state as handler of current value.

ajbee
  • 3,511
  • 3
  • 29
  • 56
  • Everytime you update state via hook or call setState component will be force to re-render to show the change, there is side way to do change in state without rendering it will be instead of doing => this.setState({data:"any value"}) do this this.state.data = "any value", as this will not render and will show any changes but it will change in state. – Amit Chauhan Sep 26 '19 at 07:37

3 Answers3

1

React.memo will stop your child component rendering if the parent rerenders (and if the props are the same), but it isn't helping in your case because you have defined the component inside your App component. Each time App renders, you're creating a new reference of MemoInput.

Updated example: https://codesandbox.io/s/currying-tdd-mikck

wrsx
  • 579
  • 3
  • 8
1

Link to Sandbox:

https://codesandbox.io/s/musing-kapitsa-n8gtj

App.js

  // const MemoInput = memo(
  //   props => {
  //     console.log(props);
  //     return <ShowIndicator name={props.name} />;
  //   },
  //   (prev, next) => console.log("prev", prev, next)
  // );

  const renderList = () => {
    return indicators.map((data,index) => {
      return <ShowIndicator key={index} name={data} />;
    });
  };

ShowIndicator.js

import React from "react";

const ShowIndicator = ({ name }) => {
  console.log("rendering showIndicator");
  const renderDatas = () => {
    return <div key={name}>{name}</div>;
  };

  return <>{renderDatas()}</>;
};

export default React.memo(ShowIndicator);    // EXPORT React.memo
cbdeveloper
  • 27,898
  • 37
  • 155
  • 336
1

Observing the given sandbox app behaviour, it seems like the whole app renders for n times when there are n indicators.

I forked the sandbox and moved the list to another functional component (and memo'ed it based on prev and next props.

This will ensure my 'List' is rendered every time a new indicator is added. The whole app will render only when a new indicator is added to the list.

Checkout this sandbox forked from yours - https://codesandbox.io/embed/avoid-re-renders-react-l4rm2

pritam
  • 2,452
  • 1
  • 21
  • 31
  • do you think it's ok to use useRef for the text value? – ajbee Sep 26 '19 at 08:04
  • 1
    React.org recommends to avoid using refs for anything that can be done declaratively. For this you could maintain the text value that is available at the parent state, and pass it down as props. – pritam Sep 26 '19 at 11:30