user3142695
user3142695

Reputation: 17342

React: Initiate values in render() or componentDidMount()?

I'm not quite sure where to initiate calculated values in a react component. So this is how I am doing it right now:

render () {
  const { foo } = this.props
  const { bar } = this.state

  const calculatedValue = bar ? foo * bar : foo

  return (
    <div>{calculatedValue}</div>
  )
}

Or should I initiate calculatedValue in componentDidMount()

Upvotes: 3

Views: 2135

Answers (3)

renanpallin
renanpallin

Reputation: 326

This depends on how your calculated value is going to change in your application. If is a value that will not change, your just wanna when the first render of the component (what you probably not), you're fine calculating in componentDidMount and assigning to a property (this.calculatedValue = ...) and accessing in render with this.calculatedValue, but it's not the "React way".

Assuming you're using the state, something that will be change in your application, then you will need to put your calculation in somewhere else.

Here are some options to you to keep your calculated values:

1. In your render method, just like you did:

Fine for simple calculations, but believe me, this thinks can grow...

render () {
    const { foo } = this.props
    const { bar } = this.state

    const calculatedValue = bar ? foo * bar : foo

    return (
        <div>{calculatedValue}</div>
    )
}

2. In a getter method:

keeping the calculation separated for your render method

getCalculatedValue() {
    const { foo } = this.props
    const { bar } = this.state

    return bar ? foo * bar : foo
}

render () {
    return (
        <div>{ this.getCalculatedValue() }</div>
    )
}

3. [ES6] With a getter property:

Just a variation for the option above, but a little more cleaner since your aren't calling a method, just accessing a property and your function is running "under the table".

get calculatedValue() {
    const { foo } = this.props
    const { bar } = this.state

    return bar ? foo * bar : foo
}

render () {
    return (
        <div>{ this.getCalculatedValue }</div>
    )
}

4. In the parent component, making this one just to show the value:

This one is a little more complex, but usually is better for growing projects. Here we will separate your component in two: The first will calculate (here you can access some API or anywhere your value was coming from) and the child one will just show it's value. This way you can keep the logic and the ui in different components, improving your reuse of code among your project. Is a good pattern to keep your UI components (the child one) in a functional component without state, but this is for another question.

/* A functional component. Is just like a class, but without state */
const MyUIComponent = props => <div>{ props.value }</div>


class MyLogicalComponent extends React.Component {
    render(){
        /* you can choose any of the options above to calculate */
        const computedValue = 5 + 8;

        return (
            <div>
                <MyUIComponent value={ computedValue } />
            </div>
        )
    }
}

Hope it helps!

Upvotes: 2

RBT
RBT

Reputation: 25937

calculatedValue is a const variable having block scope in your Render function. If you need to use its value in Render function there is no option but to calculate it in Render function only.

componentDidMount = () => {
  const { foo } = this.props
  const { bar } = this.state

  const calculatedValue = bar ? foo * bar : foo //block scope
}

If you declare the variable calculatedValue in componentDidMount() function as shown above then it will not be accessible in Render function which gets called later in the lifecycle of a reactJs component.

render = () => {

  //calculatedValue will give undefined error. calculatedValue is not known to render function
  return (
    <div>{calculatedValue}</div>
  )
}

Upvotes: 0

Luke Glazebrook
Luke Glazebrook

Reputation: 580

I think it really depends on how much calculation you are doing. For something as simple as your example above I would usually just do that in render().

Anything above very basic functionality and I would split it out into a separate function such as getFooBarCalcValue().

This way your render method doesn't get too cluttered with things that would otherwise be elsewhere.

Upvotes: 4

Related Questions