React卸载和重新挂载子组件

12
我有一个通过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>      
            )
        }
    }
2个回答

16

因为CKEditor只在挂载时使用“content”属性,所以当父组件的local.use_lang更改时,我需要重新渲染该组件。

可以通过给CKEditor一个键(key)属性等于应强制重新渲染的值来强制重新渲染CKEditor:

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

每当语言属性更改时,React就会创建一个新的CKEditor。

请注意,我使用这个解决方案是因为CKEditor是一种外部组件库,我是通过npm安装的。如果我在使用自己的代码,我会直接更改编辑器如何使用其props。但是,由于我拒绝更改外部库的代码,这就是允许我强制重新渲染而不必触及编辑器代码内部的解决方案。


1
例如使用react-google-maps:key={JSON.stringify(this.props.defaultCenter) + this.props.defaultZoom} - Dorian

0

这是因为没有检测到任何更改,因此不会再次调用render(),也不会再次调用getContent()

您可以将内容作为状态的一部分(根据构造函数,它已经是了),并在componentWillReceiveProps()中检查是否更新了use_lang。如果是,则可以通过调用this.setState({...rest, content = getContent()})来在那里更新状态。

然后您的组件render()函数应该如下所示:

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

(顺便提一下,通过调用 setState(),这将进而触发对 render() 的调用,如果检测到任何更改,则会显示更改。但请注意,这实际上并没有重新安装组件,它只是更新了视图。换句话说,在此情况下更新状态后,componentWillMount()componentDidMount() 将不会被调用。相反,将调用 componentWillUpdate()componentDidUpdate())。在此处阅读有关组件生命周期的更多信息


我已经尝试过这个了。我创建了一个简单的案例,在编辑器下面添加了一个额外的输入字段。它们都会读取“state.content”的值,而内容将是一个简单的字符串(而不是嵌套对象)。虽然在CKEditor中写入时输入字段会改变其视图,但反之则不成立。 - jaimefps
CKEditor是一个模块。这是一个我没有构建但通过npm安装的组件。我认为修改外部组件库的代码并不是一个好的做法,因此我只想找到一个不需要向CKEditor组件添加代码的解决方案。 - jaimefps

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接