React 不会根据条件渲染后调用的道具更改渲染

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

我有一个带有条件渲染的组件:'if the component has the prop "showCross" then display a button with a cross, unless nothing'。 一切正常,有showCross就有cross,除非什么都没有:

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

但问题是当我在另一个组件中使用这个组件时,即使将 prop 传递给 false,十字仍然显示(我想隐藏它):

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

控制台没有错误,只是没有按预期显示。 通过React developer tool我可以看到props如预期的那样为false,但是显示不符合显示条件(即:'display nothing')。 在它上面有故事书,但我不确定这是否与显示问题有关:

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}
        />
    )
  1. CrossButton 函数移出 RefundFormContent 组件
  2. 也很高兴看到 RefundFormContent(最好有一个 jsbin 演示)
  3. 您在 RefundFormContent 的渲染中使用 showCross<CrossButton showCross /> 但它不是通过道具定义的:const { fields, onClose, showCross } = this.props
import PropTypes from 'prop-types'
import React from 'react'
import {Cell} from 'react-mdl/lib/Grid'

const CrossButton = (props) => {
        return <div>{props.visible ? <button
              className="mdl-button mdl-js-button mdl-button--icon"
              onClick={props.onClick}>x</button> : null}</div>
    }


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

    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 visible={this.props.showCross} onClick={this.props.onClose}/>
            </Cell>
        </React.Fragment>
    )
  }
}

export default RefundFormContent

或者,如果应该使用短路显示,则只能调用 CrossButton,因此在上面的代码中,对 CrossButton 的更改为:

const CrossButton = (props) => {
        return <div><button
              className="mdl-button mdl-js-button mdl-button--icon"
              onClick={props.onClose}
          >x</button></div>
    }

并且在 RefundFormContentrender 中,您将使用:

//...
<Cell col={1} className="mdl-typography--text-right">
            {this.props.showCross && <CrossButton onClick={this.props.onClose}/>}
        </Cell>
//...

编辑:

要验证 RefundFormContent 是否有效,只需将其呈现为:

<RefundFormContent fields={fields} showCross={true} onClose={onClose}/>

注意上面的fieldsonClose一定是你要使用的道具

上面的问题是,在 OP 中调用 RefundFormContent 是正确的方法吗?:

<Form component={RefundFormContent}
            componentProps={{onClose}}
            fields={fields}
            showCross={false}
        />

这里混合了 props,如果 Form 将上面的内容正确地传递给 RefundFormContent,那么它应该都可以正常工作。

RefundFormContent 中你没有传递 showCross,只是告诉元素总是 "showCrossed"..

<input type="checkbox" checked />相同。

您将像这样使用它:

<CrossButton showCross={this.props.showCross} />

由于您的回答让我走上了正确的道路,我找到了问题:

  • 三进制有效
  • 道具通过组件很好地传递

--> 问题是在每个组件中定义一个 defaultProps 以清楚地说明预期的行为。 (我认为调用或不调用 showCross 会告诉我是否要显示十字架,但不是)。 所以你可以使用类似的东西:

static defaultProps = {
    showCross: false,
}

或:

const {showCross=false} = this.props;

并在 return

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

如果 showCross = false,则不显示十字,如果 showCross = true,则显示。