web-dev-qa-db-ja.com

React子コンポーネントのマウント解除と再マウント

マウント時の親コンポーネントの状態のみを考慮するnpmインポートコンポーネント(CKEditor)があります。つまり、親コンポーネントの状態がどのように変化しても、CKEditorは、すでにマウントされている場合、それらの変更を反映しません。

親コンポーネントが言語プロパティを変更したときに、CKEditorが親コンポーネントの状態に基づいて変更する必要があるため、これは私にとって問題です。

子コンポーネントをマウント解除して親コンポーネントから再度マウントする方法はありますか?たとえば、親コンポーネントの「componentWillReceiveProps」に基づいて子コンポーネントをアンマウントして再度マウントする方法はありますか?

    import React from 'react';
    import CKEditor from "react-ckeditor-component";

    export default class EditParagraph extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                // an object that has a different html string for each potential language
                content: this.props.specs.content,
            }
            this.handleRTEChange = this.handleRTEChange.bind(this)
            this.handleRTEBlur = this.handleRTEBlur.bind(this)
        }

        /**
         * Native React method 
         *  that runs every time the component is about to receive new props.
         */
        componentWillReceiveProps(nextProps) {
            const languageChanged = this.props.local.use_lang != nextProps.local.use_lang;
            if (languageChanged) {
                // how do I unmount the CKEditor and remount it ???
                console.log('use_lang changed');
            }
        }

        handleRTEChange(evt) {
            // keeps track of changes within the correct language section
        }

        handleRTEBlur() {
            // fully updates the specs only on Blur
        }

        getContent () {
            // gets content relative to current use language
        }

        render() {
            const content = this.getContent();

            // This is logging the content relative to the current language (as expected), 
            // but CKEditor doesn't show any changes when content changes.
            console.log('content:', content);

            // I need to find a way of unmounting and re-mounting CKEditor whenever use_lang changes.
            return (
                <div>
                    <CKEditor 
                        content={content} 
                        events={{
                            "blur": this.handleRTEBlur,
                            "change": this.handleRTEChange
                        }}
                    />
                </div>      
            )
        }
    }
7
jaimefps

CKEditorはマウント時に「コンテンツ」プロップのみを使用するため、親コンポーネントのlocal.use_langが変更されたときにコンポーネントを再レンダリングする必要がありました。

CKEditorは、key propに、再レンダリングを強制する必要がある値と等しい値を与えることによって、強制的に再レン​​ダリングすることができます。

<CKEditor key={this.props.local.use_lang} etc />

このように、言語の小道具が変更されるたびに、Reactは新しいCKEditorを作成します。

CKEditorはnpmでインストールした外部コンポーネントライブラリであるため、このソリューションを利用したことを覚えておいてください。それが私が使用していた自分のコードである場合は、エディターがプロップを使用する方法を変更するだけです。ただし、外部ライブラリコードへの変更を拒否するため、これは、エディターコードの内部に手を加える必要なく、再レンダリングを強制できるソリューションです。

8
jaimefps

これは、変更が検出されなかったため、render()を再度呼び出さず、getContent()を再度呼び出すことはありません。

あなたができることは、コンテンツを状態の一部にすることです(これはあなたのコンストラクタによると、すでにあります)、_use_lang_が更新されているかどうかをcomponentWillReceiveProps()にチェックインします。その場合は、this.setState({...rest, content = getContent()};を呼び出して状態を更新できます。

そして、コンポーネントのrender()関数は次のようになります

_<CKEditor 
    content={this.state.content} 
    events={{
        "blur": this.handleRTEBlur,
        "change": this.handleRTEChange
    }}
/>
_

(余談ですが、setState()を呼び出すと、render()への呼び出しがトリガーされ、変更が検出された場合、変更が表示されます。ただし、これはコンポーネントを実際に「再マウント」するのは、ビューを更新するだけです。つまり、この状況では、状態を更新した後、componentWillMount()およびcomponentDidMount()は呼び出されません。代わりに、componentWillUpdate()およびcomponentDidUpdate()が呼び出されます)。 コンポーネントのライフサイクルについて詳しくは、こちらをご覧ください

0
sme