一次更新多个组件中的状态

时间:2015-05-14 07:52:06

标签: reactjs

我有一个listview组件,它由许多子列表项组件组成。

每个子列表项都有一个showSubMenu布尔状态,它会在列表项旁边显示一些额外的按钮。

此状态应更新以响应用户事件,例如,单击组件DOM节点。

childcomponent:

_handleClick() {
  ... mutate state
  this.props.onClick() // call the onClick handler provided by the parent to update the state in parent
}

然而,更新状态感觉有点不对,因为它会在不同的地方改变状态。

我认为我可以完成它的另一种方式是直接调用this.props.onClick,然后将子状态作为道具移动到父项中,然后在那里更改状态,并将其作为道具涓涓细流

这些方法中哪些(如果有的话)是惯用的还是更可取的?

2 个答案:

答案 0 :(得分:2)

首先,我认为问题的标题并不能很好地描述你的疑问。关于国家应该去哪里更是一个问题。

React的theory说你应该把你的状态放在你能找到的更高的组件中,作为一组组件的唯一真实来源。

  

对于您申请中的每个州:

     
      
  • 根据该状态确定呈现某些内容的每个组件。
  •   
  • 找到一个共同的所有者组件(单个组件位于所有组件之上   需要层次结构中的状态的组件。
  •   
  • 要么是共同的   所有者或层次结构中较高的其他组件应该拥有   州。
  •   
  • 如果你找不到合适的组件来拥有它   state,创建一个新组件,只是为了保持状态并添加它   公共所有者组件上方层次结构中的某个位置。
  •   

然而,Facebook said的软件工程师:

  

我们从大型顶级组件开始,提取所有数据   他们的孩子需要,并通过道具传递下去。这导致   中间组件中的许多残缺和无关的代码。   我们在大多数情况下确定的是组件声明和   获取他们自己需要的数据......

当然,正在讨论从商店获取的数据,但我要说的是,在某些情况下理论并不是最佳选择。

在这种情况下,我会说showSubMenu状态只对列表项有意义,以显示几个按钮,因此它是一个很好的选项,将该状态放在子组件中。我说这是一个很好的选择,因为它是一个简单问题的简单解决方案,你提出的另一个选择意味着有类似this的东西:

var GroceryList = React.createClass({
  handleClick: function(i) {
  console.log('You clicked: ' + this.props.items[i]);
},

render: function() {
  return (
    <div>
      {this.props.items.map(function(item, i) {
        return (
          <div onClick={this.handleClick.bind(this, i)} key={i}>{item} </div>
        );
      }, this)}
    </div>
  );
}
});

如果将来列表视图必须获得该状态的确认以显示某些内容,那么状态应该在父组件中。

然而,我认为这是一条细线,你可以在你的特定情况下做一个有意义的事情,我在我的应用程序中有一个非常相似的情况,这是一个简单的案例,所以我把状态放在孩子身上。明天也许我必须改变它并把状态放在他的父母身上。

答案 1 :(得分:0)

许多组件都取决于相同的状态及其变异,您将遇到两个问题。

  1. 它们被放置在组件树中,以至于您的状态必须存储在渲染树中非常高的父组件中。
  2. 将状态放置在离子级组件很远的地方,您将不得不将它们传递给许多不知道该状态的组件。

此问题有两种解决方案!

  1. 使用React.createContext和用户上下文提供程序将数据传递给子元素。
  2. 使用redux和react-redux库将状态保存在存储中,并将其连接到应用程序中的不同组件。供您参考,react-redux库在幕后使用React.createContext方法。

示例:

创建上下文

const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Use a Provider to pass the current theme to the tree below.
    // Any component can read it, no matter how deep it is.
    // In this example, we're passing "dark" as the current value.
    return (
      <ThemeContext.Provider value="dark">
    <Toolbar />
      </ThemeContext.Provider>
    );
  }
class ThemedButton extends React.Component {
  // Assign a contextType to read the current theme context.
  // React will find the closest theme Provider above and use its value.
  // In this example, the current theme is "dark".
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}
}

// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // Assign a contextType to read the current theme context.
  // React will find the closest theme Provider above and use its value.
  // In this example, the current theme is "dark".
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

REDUX和REACT-REDUX

import { connect } from 'react-redux'

const App = props => {
  return <div>{props.user}</div>
}

const mapStateToProps = state => {
  return state
}

export default connect(mapStateToProps)(App)

有关redux和react-redux的更多信息,请查看以下链接: https://redux.js.org/recipes/writing-tests#connected-components