简体   繁体   中英

React Functional Component - Store some prop calculation in const vs state

I have a component which renders only once and then is being destroyed, I've implemented the "Comp3" way.

Using "useEffect" to calculate the str with the num value I received as a prop, then stored the result using "useEffect" setter in order to use the result in the html.

//Let say this function is inside the functional component
function numToStr(num:number):string{
  switch(num){
    case 1:
      return "One";
    case 2:
      return "Two";
    ...
  }
}
function Comp1({num:number}){
  const numAsStr = numToStr(num);
  return <span>{numAsStr}</span>
}
function Comp2({num:number}){
  const [numAsStr] = useState(numToStr(num));
  return <span>{numAsStr}</span>
}
function Comp3({num:number}){
  const [numAsStr,setNumAsStr] = useState();
  useEffect(()=>{
    setNumAsStr(numToStr(num));
  },[])
  return <span>{numAsStr}</span>
}
function Comp4({num:number}){
  const numAsStr = useMemo(()=>numToStr(num),[]);
  return <span>{numAsStr}</span>
}

My question is:

What is the best solution in terms of best-practice/ "react-way" ?

How each implementation effect the performance ?

Does the fact that I know the component only renders once should impact way I choose to implement?

Or should I treat this component as if i don't know it should be render once and in this case still support the option to "watch" over the prop being changed? (add it to the useEffect / useMemo arrays)

Thanks!

If the calculations being done by strToNum are cheap (as they are in your simplified example), then the approach in Comp1 is probably the best and simplest. They'll run each time the component re-renders, so they're always up-to-date.

If the calculations are expensive, the recommended way to deal with this is the useMemo hook , like in your Comp4 example. However, you'd want to make sure to include num input variable in your dependents array so that numAsStr gets re-computed whenever num changes. Eg:

function Comp4({num:number}){
  const numAsStr = useMemo(()=>numToStr(num),[num]);
  return <span>{numAsStr}</span>
}

Using useState as you have in Comp2 would only run numToStr in the initial render, so you'd get stale values if num ever changed.

Using useEffect as you have in Comp3 introduces an unnecessary double-render - eg it renders first without a value for numAsStr and then renders again.

I know you said that you are currently sure that it never re-renders again - so some of the downsides/gotchas mentioned above might not apply in this case (and then I'd just go with the Comp1 approach, because it's simpler) but in my experience, it's best not to make that assumption - will you (or a team-mate) remember that in a month when you try to refactor something?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM