如何创建共享功能但具有独立状态的react组件

How to create react components which share functions but have independent state?

本文关键字:独立 状态 组件 react 功能 何创建 创建 共享      更新时间:2023-09-26

我想创建两个React组件。它们需要共享共同的功能。这些函数使用this.setState(),因此我不能将它们放在帮助文件中。我试着用composition。这使我能够共享函数,但它们也共享状态。

我需要像

这样的东西
//file 1
var Component1 = React.createClass({
    getInitialState() {
        return {
            //return some common + new states
        }
});
//file 2
var Component2 = React.createClass({
    getInitialState() {
        return {
            //return some common + new states
        }
});
// file 3
// This file needs to have some functions, which can do:
this.setState(); //on state of Component1 and Component2.

这里有几个选项。

商店

如果这些组件是完全独立的,您可以使用一个存储来保存和更新每个组件使用的数据,并订阅该存储。这是Flux/Redux模式。

一个组件可能看起来像这样

class Component1 extends React.Component {
  constructor(...props) {
    super(...props)
    this.update = this.update.bind(this)
    this.state = { count: 0 }
  }
  update (storeData) {
    this.setState(storeData)
  }
  componentDidMount () {
    store.subscribe(this.update)
  }
  componentDidUnmount () {
    store.unsubscribe(this.update)
  }
  render () {
    return (<span>You have clicked {this.state.count} times</span>)
  }
}
这里需要注意的是,store不能直接访问组件的状态。组件订阅,其他机制将发布数据。商店将调用注册的回调。一个非常简单存储可能看起来像这样
const store = {
  subscriptions: new Set(),
  data: {},
  subscribe: function (callback) {
    this.subscriptions.add(callback)
  },
  unsubscribe: function (callback) {
    this.subscriptions.delete(callback)
  },
  update: function (key, value) {
    this.data[key] = value
    this.subscriptions.forEach(cb => cb(this.data))
  }
}

这允许任何访问存储的人更新任何/所有订阅的组件。

const CounterButton = () => (
  <button onClick={() => store.update('count', (store.data.count || 0) + 1)}>Increase Count</button>
)

这是一个非常做作的代码依赖来演示这个

<标题> 父组件

如果你的组件都是共享组件的子组件,那么它们的父组件可以通过更新它们的props来更新它们,而不是更新它们的状态。它可以使用自己的内部状态来跟踪这个。

class ParentComponent extends React.Component {
  constructor(...props) {
    super(...props)
    this.state = { clicks: 0 }
  }
  render () {
    return (
      <div>
        <button onClick={() => this.setState({ clicks: this.state.clicks + 1})}>Increase Count</button>
        <Component1 clicks={this.state.clicks} />
        <Component2 clicks={this.state.clicks} />
      </div>
    )
  }
}
const Component1 = ({clicks}) => (
  <span>You have clicked {clicks} times</span>
)
const Component2 = (props) => (
  <span>You have pressed {props.clicks} times</span>
)

这是一个同样人为的代码依赖来演示这个

Something crazy else

以上两种是推荐的方法。但这是JavaScript,我们的规则比狂野西部还少。如果你真的想从某个共享函数直接控制组件的状态,没有什么能阻止你

var sharedComponents = new Set()
function incrementComponents () {
  sharedComponents.forEach(c => c.setState({clicks: c.state.clicks + 1}))
}
class Component1 extends React.Component {
  constructor(...props) {
    super(...props)
    this.state = { clicks: 0 }
    sharedComponents.add(this)
  }
  render () {
    return (<span>You have clicked {this.state.clicks} times</span>)
  }
}
setInterval(incrementComponents, 1000)

这是一个完全疯狂的合作者证明这一点。

保持Component1 &Parent component下的Component2,如果你将父组件函数传递给子组件,那么Component1 &Component2将具有Parent Componentprops的功能。所以你得到你的common功能像这样的反应组件在parent-child relationship中工作。孩子们可以从他们的父母那里获得数据。这样你所有的子组件也都有自己的状态