メンチカツ

ロースカツが好きです

React + React Bootstrap で、htmlでお知らせが書けるツールチップを使いたい

こういうやつが欲しい。

f:id:easy-breezy:20160608154337p:plain

そこで

<Info message={message} />

こういうコンポーネントを作成したところ、messageに与えた文字列のhtmlタグがエスケープされて、そのまま出力されてしまう。

<Info message="Hello,<br/><br/><strong>world!!!!!!</strong>" />

// => Tooltipに「Hello,<br/><br/><strong>world!!!!!!</strong>」

それで、同じ壁にぶち当たってる人を探したら、いた。

stackoverflow.com

なるほどArrayで渡せば良いらしい。

<Info message={[
    "Hello,", <br/>, <br/>,
    <strong>world!!!!!!</strong>, <br/>
]}/>

これをInfoコンポーネントの中で this.props.message.join() すればよいのか、と思いきや、

Warning: Each child in an array or iterator should have a unique "key" prop.

キーつけなさいよ!っておこられる。上のリンク先にもそうレスがありますね。

というわけでキーをつけます。

getMessage() {
        return this.props.message.map(function (m, index) {
            return <span key={index}>{m}</span>
        })
}

できあがったものはこちら。

import React, { PropTypes, Component } from 'react'
import { Tooltip, OverlayTrigger } from 'react-bootstrap'
import SHA256 from 'crypto-js/sha256'

class Info extends Component {

    static propTypes = {
        message: PropTypes.array.isRequired,
        placement: PropTypes.string
    }

    getMessage() {
        return this.props.message.map(function (row, index) {
            return <span key={index}>{row}</span>
        })
    }

    render() {
        const message = this.getMessage()
        const tooltip = <Tooltip id={SHA256(new Date()).toString()}>{message}</Tooltip>
        return (
            <span className="info">
                <OverlayTrigger placement={this.props.placement} overlay={tooltip}>
                    <i className="fa fa-info-circle"></i>
                </OverlayTrigger>
            </span>
        )
    }
}

export default Info

2016/08/10追記

パラメータのところ

<Info message={[
    "Hello,", <br/>, <br/>,
    <strong>world!!!!!!</strong>, <br/>
]}/>

は、要はjsxの書式ならOKなので、

<Info message={[<span>Hello,<br/><br/><strong>world!!!!!!</strong><br/></span>]}/>

こっちのほうがスッキリしますね。