Reactjs使组件可由其他组件控制的最佳实践



我有一个像弹出窗口一样显示的Chat组件。我想让用户有可能打开/关闭它作为更深层次组件的操作。我花了几个小时在上面,因为我将对其他组件使用相同的模式。我真的很感激一个干净/反应的解决方案!

到目前为止,我设法做了一些工作,但看起来真的很笨拙。


EDIT:我做了一个单独的例子,让它看起来更好。仍然想知道React方式是什么。

import React, { Component } from 'react';
var instance = null;
class Chat extends Component {
constructor(props) {
super(props);
this.state = {
show: false
};
}
render() {
return this.state.show ? (<div>CHAT WINDOW</div>) : null;
}
open  = () => this.setState({show: true})
close = () => this.setState({show: false})
}
export const openChat = () => instance.open();
export default function ChatSingleton(props) {
if (instance === null)
instance = new Chat(props);
return instance;
}

现在我可以全局调用open/close方法,如下所示:

import {openChat} from 'components/Chat';
export default function Foo(props) {
return (<div onClick={openChat}>Open Chat</div>);
}

我在SO上找到了使用Redux或React Context的类似问题的解决方案,但我真的想要一个简单的解决方案。HOC可以。

谢谢!

在寻找解决方案之前,请尝试了解"show"状态是否必须属于chat或他的父亲(责任链模式(一旦你了解了这一点,以下是一些可能的解决方案

使用props:

class Parent extends Component {
constructor(props) {
super(props);
this.state = {
showChat: false
};
}
openChat  = () => this.setState({showChat: true})
closeChat = () => this.setState({showChat: false})
render() {
return (
<div>
<Chat show={this.state.showChat}>
<Foo onOpenClick={this.openChat} onCloseClick={this.closeChat}>
</div>
}
}

使用Context:


class MyProvider extends React.Component {
state = {
isOpen: false
};
openChat = e => {
this.setState({ isOpen: true });
};
closeChat = e => {
this.setState({ isOpen: false });
};
render() {
return (
<MyProvider
value={{
state: this.state,
openChat: this.openChat,
openChat: this.closeChat
}}
>
<div >{this.props.children}</div
</MyProvider>
);
}

应用程序:

import { MyProvider } from './ChatContext';
<MyProvider>
<Chat />
<OtherComponent>
<Foo>
</OtherComponent>
</MyProvider>

Foo:


import React, { Component } from 'react';
import { MyConsumer } from './ChatContext';
class Foo extends Component {
state = {};
render() {
return (
<MyConsumer>
{({ openChat }) => (
<div>
This is Foo
<button onClick={openChat}>open</span>
</div>
)}
</MyConsumer>
);
}
}
export default Foo;

阅读有关上下文的更多信息:https://kentcdodds.com/blog/how-to-use-react-context-effectively


或使用React-redux:https://react-redux.js.org/

最新更新