web-dev-qa-db-fra.com

Réagir démonter et remonter composant enfant

J'ai un composant importé par npm (CKEditor) qui ne se préoccupe que de l'état de son composant parent au moment de son montage. En d'autres termes, quels que soient les changements intervenus dans l'état du composant parent, CKEditor ne reflétera pas ces changements s'il a déjà été monté.

C’est un problème pour moi car j’ai besoin que CKEditor change en fonction de l’état du composant parent lorsque le composant parent change de propriété. 

Puis-je faire en sorte qu'un composant enfant soit démonté et remonté à partir du composant parent? Par exemple, est-il possible pour moi de démonter et de remonter un composant enfant en fonction du composant "composantWillReceiveProps" du composant parent?

    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>      
            )
        }
    }
4
jaimefps

CKEditor n'utilisant que "content" prop lorsqu'il se monte, il fallait que je rende à nouveau le composant lorsque le local.use_lang du composant parent change. 

CKEditor peut être obligé de refaire le rendu en lui donnant un prop key égal à la valeur qui devrait le forcer à refaire le rendu:

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

De cette façon, chaque fois que l’élément linguistique change, React crée un nouveau CKEditor.

N'oubliez pas que j'ai utilisé cette solution car CKEditor est une bibliothèque de composants étrangers que j'ai installée avec npm. Si je travaillais avec mon propre code, je modifierais simplement la façon dont l'éditeur utilise ses accessoires. Cependant, comme je refuse d’apporter des modifications au code d’une bibliothèque étrangère, c’est la solution qui m’a permis de forcer une nouvelle restitution sans avoir à toucher aux éléments internes du code de l’éditeur.

5
jaimefps

C’est parce qu’aucun changement n’a été détecté. Par conséquent, il n’appellera plus render() et ne fera donc aucun autre appel à getContent().

Ce que vous pouvez faire, c'est que le contenu fasse partie de l'état (ce qui, selon votre constructeur, le soit déjà) et vérifiez dans componentWillReceiveProps() si le use_lang est mis à jour. Si c'est le cas, vous pouvez alors mettre à jour l'état en appelant this.setState({...rest, content = getContent()};

Et ensuite, votre fonction composant render() devrait ressembler à ceci

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

(En passant, en appelant setState(), ceci déclenchera à son tour un appel à render(), et si des modifications étaient détectées, les modifications seraient affichées. Notez cependant qu'il ne s'agit pas en fait de remonter le composant, En d’autres termes, componentWillMount() et componentDidMount() ne seront pas appelés après la mise à jour de l’état dans cette situation, mais componentWillUpdate() et componentDidUpdate() seront appelés). En savoir plus sur le cycle de vie des composants ici

0
sme