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}
/>
)
- 将
CrossButton
函数移出 RefundFormContent
组件
- 也很高兴看到
RefundFormContent
(最好有一个 jsbin 演示)
- 您在
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>
}
并且在 RefundFormContent
的 render
中,您将使用:
//...
<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}/>
注意上面的fields
和onClose
一定是你要使用的道具
上面的问题是,在 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,则显示。
我有一个带有条件渲染的组件:'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}
/>
)
- 将
CrossButton
函数移出RefundFormContent
组件 - 也很高兴看到
RefundFormContent
(最好有一个 jsbin 演示) - 您在
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>
}
并且在 RefundFormContent
的 render
中,您将使用:
//...
<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}/>
注意上面的fields
和onClose
一定是你要使用的道具
上面的问题是,在 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,则显示。