以下是React中的反模式吗?我喜欢这种模式,因为当实例化一个组件时,它在静态函数中为我提供了上下文。然后,我可以导入该类并调用静态方法来修改状态。还是可以通过更好的方式来完成?
// componentA.js function bleedContext() { ComponentA.staticMethod = ComponentA.staticMethod.bind(this) } export default class ComponentA { static staticMethod() { this.setState({foo: 'bar'}) } constructor() { this.state = {} bleedContext.call(this) } render() { return ( ... ) } } // componentB.js import ComponentA from 'path/to/componentA' export default class ComponentB { handleClick() { ComponentA.staticMethod() } render() { return ( <button onClick={this.handleClick} /> ) } }
显然,这取决于条件,可能是一种反模式,也可能是一个错误。静态类方法不应与类实例一起使用。staticMethod绑定到特定的组件实例和用途setState,这只能证明类是单例是合理的(尽管单例也经常是反模式)。如果期望有多个类实例,那么这将导致错误和内存泄漏,并且至少对于测试而言,每个React组件均应具有多个实例。
staticMethod
setState
两个独立组件在React中彼此交互的一种正确方法是拥有一个提供此交互的公共父组件,例如:
class ModalContainer extends Component { modalRef = React.createRef(); render() { return <> <Modal ref={this.modalRef} /> <SomeComponentThatUsesModal modalRef={this.modalRef} /> </>; } }
上面示例的问题是,modalRef如果<SomeComponentThatUsesModal>嵌套,这将需要深入传递属性。
modalRef
<SomeComponentThatUsesModal>
这个问题可以通过React上下文或其他第三方全局状态解决方案(例如Redux)来解决。
考虑到Modal类实例具有open方法,可以使用React 16.3上下文API完成此操作:
Modal
open
const ModalContext = React.createContext(); function getModal(modalRef) { return { open: data => modalRef.current.open(data); close: () => modalRef.current.close(); } } class ModalContainer extends Component { modalRef = React.createRef(); render() { return <> <Modal ref={this.modalRef} /> <ModalContext.Provider value={getModal(this.modalRef)}> {this.props.children} </ModalContext.Provider> </>; } }
然后,对于任何深层嵌套的组件模态对象,open可以通过context 使用with 和close方法:
const SomeComponentThatUsesModal = props => <div> <ModalContext.Consumer> {modal => <button onClick={() => modal.open('foo')} />} </ModalContext.Consumer> </div>; <ModalContainer> ...deeply nested component <SomeComponentThatUsesModal /> ... </ModalContainer>
这是一个演示。