【问题标题】:Change props value outsite react and reload component更改道具值外部反应并重新加载组件
【发布时间】:2019-07-26 08:23:32
【问题描述】:

正如标题所说,我想在外部 js 文件中更改 props 的值并重新加载组件。

<div data-group=""></div>
//external.js
const popupChat = document.getElementById('popupChatComponent');
popupChat.setAttribute('data-group', groupId);
//component.ts
export default class PopupChatRoot extends React.Component {
    private readonly groupId: string;

    constructor(props) {
        super(props);
        this.groupId = this.props.group;
    }

    render() {
        return (
            <div className="modal-body">
                <p>{this.groupId}</p>
            </div>
        );
    }
}

const component = document.getElementById('popupChatComponent');
if (component) {
    const props = Object.assign({}, component!.dataset);
    render(<PopupChatRoot {...props}/>, component);
}

我该怎么做?

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

这只是一个通用示例,它可能会帮助您解决问题。其实我不认为你可以改变根节点的道具。

// yourEventService.js
class YourEventService {

  listeners = []

  subscribe = listener => this.listeners.push(listener)

  unsubscribe = listener => this.listeners = this.listeners.filter(item => item !== listener)

  emit = message => listener.forEach(listener => listener(message))

}

export default new YourEventService() // singleton export
// someWhereElse.js

import yourEventService from './yourEventService'

window.addEventListener('click', () => yourEventService.emit('myNewGroup')) // it's just an event example

//component.js, sorry I don't know how to typescript well
import yourEventService from './yourEventService'

export default class PopupChatRoot extends React.Component {

    state = {
        groupId: this.props.group; // initial value is passed by props
    }


    componentDidMount() {
        yourEventService.subscribe(this.handleMessage)
    }

    componentWillUnmount() {
        yourEventService.unsubscribe(this.handleMessage)
    }

    handleMessage = message => {
        this.setState({ groupId: message })
    }

    render() {
        return (
            <div className="modal-body">
                <p>{this.state.groupId}</p>
            </div>
        );
    }
}

const component = document.getElementById('popupChatComponent');
if (component) {
    const props = Object.assign({}, component.dataset);
    render(<PopupChatRoot {...props}/>, component);
}

【讨论】:

    【解决方案2】:

    您可以做的是使用包装器组件或更高阶的组件,它为您的组件提供这些道具,并让该包装器组件与您的外部 javascript 代码集成。

    这是我用来做类似事情的 HOC:

    export interface MyHocProps {
        //the props you want to provide to your component
        myProp: any;
    }
    
    export const withMyHOC = <T extends any>(params: any) =>
    
    <P extends MyHocProps>(WrappedComponent: React.ComponentType<P>): React.ComponentClass<defs.Omit<P, keyof MyHocProps>> => {
    
        return class extends React.PureComponent<defs.Omit<P, keyof MyHocProps>> {
    
            //here you have access to params, which can contain anything you want
            // maybe you can provide some sort of observable which causes this to re-render
    
            render() {
    
                return <WrappedComponent
                    {...this.props}
                    myProp={/*whatever*/}
                />;
            }
        }
    };
    

    从这里开始,您可以将此 HOC 与某种系统集成以推动对其进行更改。我建议使用可观察的。基本上你想让这个 HOC 组件订阅一些可观察数据的变化,然后在它发生变化时强制自己重新渲染。

    或者,如果组件只是一个单例,您可以通过执行 window.reloadThisComponent = this.reload.bind(this); 之类的操作来公开组件上的某些方法,但这可能应该被视为最后的手段。

    【讨论】:

    • 使用 HOC 肯定比我的回答更好。将我的答案与这个答案合并可以帮助您解决问题。
    • 我有个问题,defs 不能被 typescript 识别,this.props 也一样。
    • 我不明白。
    • defs.Omit 是我用来从界面中删除键的自定义类型。它被实现为type Omit&lt;T, K extends keyof T&gt; = Pick&lt;T, Exclude&lt;keyof T, K&gt;&gt;。我用它来向父组件表明它不需要证明该属性,因为它是由 HOC 提供的。 this.props 应该可以识别,不知道那里发生了什么。
    猜你喜欢
    • 2021-01-19
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-05-01
    相关资源
    最近更新 更多