Search code examples
javascriptreactjsternary-operatorreact-propsstorybook

React doesn't change render according props invoked after a conditional rendering


I have a component with a conditional rendering : 'if the component has the prop "showCross" then display a button with a cross, unless nothing'. Everything works well, when there is showCross, there is the cross, unless there is nothing :

import PropTypes from 'prop-types'
import React from 'react'
import {Cell} from 'react-mdl/lib/Grid'

class RefundFormContent extends React.Component {
  render() {
    const { fields, onClose } = this.props
    const style = {width: '150px'}

    function CrossButton(props) {
        let {showCross} = props
        const displayCross =
          showCross ? <button
              className="mdl-button mdl-js-button mdl-button--icon"
              onClick={onClose}
          >x</button>
              : null
        return (
            <div>{displayCross}</div>
        )
    }


    return (
        <React.Fragment>
            <Cell col={3}>
                <Formfield {...fields.type} style={style} />
            </Cell>
            <Cell col={4}>
                <Formfield {...fields.provider} style={style} />
            </Cell>
            <Cell col={4}>
                <Formfield {...fields.amount} style={style} />
            </Cell>
            <Cell col={1} className="mdl-typography--text-right">
                <CrossButton showCross />
            </Cell>
        </React.Fragment>
    )
  }
}

export default RefundFormContent

But the problem is when I use this component in another, even the prop is passed to false, the cross is still displayed (I want to hide it) :

import PropTypes from 'prop-types'
import React from 'react'
import Grid from 'react-mdl/lib/Grid'
import Form from 'forms/Form'
import {validateCurrency} from 'forms/inputs/currency'
import {makeChoices} from 'forms/utils'
import RefundFormContent from './RefundFormContent'


const RefundForm = (
    {values=null, types, providers, onClose, showCross=false}
) => {

const fields = {
    type: {
        label: 'Type',
        choices: makeChoices(types),
        floatingLabel: true,
    },
    provider: {
        label: 'Demandeur',
        choices: makeChoices(providers),
        floatingLabel: true,
    },
    amount: {
        label: 'Montant',
        validators: [validateCurrency],
        floatingLabel: true,
        placeholder: 'euros',
    },
    comment: {
        label: 'Commentaire',
        required: false,
        floatingLabel: true,
    },
}
return (
    <Grid style={{backgroundColor: '#EEE', boxShadow: '1px 1px 5px 0 #A9A', 
     margin: '20px 0'}}>
        <Form
            component={RefundFormContent}
            componentProps={{onClose}}
            fields={fields}
            showCross={false}
        />
    </Grid>
  )
}

export default RefundForm

No error in console, just not displayed as expected. Through React developer tool I can see that the props is at false as expected, but the display doesn't follow the display condition (that is to say: 'display nothing'). On top of it there is storybook but I'm not sure that this is linked to the display problem :

import React from 'react'
import { storiesOf } from '@storybook/react'
import RefundAssignment from '../account/RefundAssignment'

storiesOf('RefundAssignment', module)
    .add('Affectation', () =>
        <RefundAssignment
            types={['1', '2', '3']}
            providers={['Deborah', 'Patrick', 'Severine', 
'Patrick Swayze']}
            showCross={false}
        />
    )

Solution

  • I've found the problem thanks to your answers that put me on the good way :

    • The ternary worked
    • Props were passed well through components

    --> The problem was to define a defaultProps in each component to tell clearly the expected behaviour. (I thought that call or not call showCross would tell if I want to display the cross or not, but no). So you can use something like :

    static defaultProps = {
        showCross: false,
    }
    

    or :

    const {showCross=false} = this.props;
    

    and in the return

    <RefundCheckbox
       types={types}
       providers={providers}
       showCross={showCross}
    />
    

    If showCross = false the cross will not be displayed, if showCross = true it will.