无论类型如何,优雅的渲染道具方式

时间:2019-02-03 13:38:48

标签: reactjs

考虑到我有一个可以接受一个道具的组件,这两个组件最简单,最优雅的工作方式是什么?

<MessageBlock message="Some message goes here" />

<MessageBlock message={() => (
    <>
        Some message <strong>goes</strong> here
    </>
} />

首先想到的是使用typeof检查道具类型,并根据如下所示渲染道具:

class MessageBlock extends React.Component {
    render() {
        const { message: Message } = this.props;

        return (
            <div className="message-block">
                {typeof Message === "function" ? (
                    <Message />
                ) : (
                    <>
                        {message}
                    </>
                )}
            </div>
        )
    }
}

1 个答案:

答案 0 :(得分:1)

这取决于您的组件应该能够做什么。

如果您希望组件能够显示其中的任何内容,我建议使用其children道具作为渲染功能:

const MessageBlock = props => (
  <div className={'add the stuff you want to wrap'}>
    {props.children()}
  </div>
)

const App = props => (
    <React.Fragment>
        <MessageBlock>
            {() => 
                <React.Fragment>
                    Some message <strong>goes</strong> here
                </React.Fragment>
            }
        </MessageBlock>
        <MessageBlock>
            {() => <p>Another message</p>}
        </MessageBlock>
    </React.Fragment>
)

ReactDOM.render(<App/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id='root'>

但是,如果您希望它不显示字符串,则将propTypes与您建议的第一个解决方案一起使用:

MessageBlock.propTypes = {
    message: PropTypes.string
};

如果您希望它同时执行,则可以定义一个||条件(如果已定义消息)。如果存在该消息,将默认显示该消息,否则将执行children函数:

const MessageBlock = ({ children, message }) => (
  <div className={'add the stuff you want to wrap'}>
    {message || children()}
  </div>
)

/*MessageBlock.propTypes = { //Proptypes are undefined in SO snippets :(
    message: PropTypes.string
};*/

const App = props => (
    <React.Fragment>
        <MessageBlock>
            {() => 
                <React.Fragment>
                    Some message <strong>goes</strong> here
                </React.Fragment>
            }
        </MessageBlock>
        <MessageBlock message={'A string message'} />
    </React.Fragment>
)

ReactDOM.render(<App/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<div id='root'>