javascript - 如果不鼓励使用 forceUpdate(),组件应该如何对模型中的更改事件使用react?

标签 javascript reactjs

我在整个应用程序的多个组件中使用以下模式。我注意到许多人不鼓励使用 forceUpdate(),有些人甚至称其为 hack。那么如何在不使用它的情况下完成呢?

// user.js

export default class User extends EventEmitter {
    constructor(args) {
        super();
        this.id = args.id;
        this.isActivated = args.isActivated || false;
    }
    activate() {
        this.isActivated = true;
        this.emit('change');
    }
}

// UserView.jsx

export default class UserView extends React.Component {
    componentDidMount() {
        this.props.user.on('change', this.onUserUpdate);
    }
    onUserUpdate() {
        this.forceUpdate();
    }
    render (
        var user = this.props.user;
        return (
            <div>
                <span>User {user.isActivated ? 'is' : 'is not'} activated.</span>
                <button onClick={user.activate()}>Activate</button>
            </div>
        );
    );
}

// app.js

var user = new User({ id: 123 });
ReactDOM.render(<UserView user={user} />, container);

最佳答案

React 会在 props 或 state 发生变化时自动渲染组件。

如果您有一个属性不断变化的模型,那么您应该将其保持在组件的本地状态。

componentWillMount() {
  this.setState({
    user: this.props.user
  });
}
activator(user) {
  return () => {
    // mutate the user instance
    user.activate();
    // update the state to trigger render
    this.setState({ user });
  };
}
render (
  var user = this.state.user;
  return (
    <div>
      <span>User {user.isActivated ? 'is' : 'is not'} activated.</span>
      <button onClick={activator(user)}>Activate</button>
    </div>
  );
)

即使这有点 hacky 并且在状态中存储不可序列化的数据(原型(prototype)关系、函数)也不是很好。我们还在对象处于状态时改变它(哎呀!)。

解决这个问题的(可以说)更优雅的方法是使用一个没有任何实例方法的简单对象来表示用户。然后编写一组纯操作函数,返回反射(reflect)变化的新用户对象。

// user factory
function User(args) {
  return {
    id: args.id,
    isActivated: args.isActivated || false
  };
}

function activate(user) {
  // returns a new copy with the isActivated property set to true
  return Object.assign({}, user, { isActivated: true });

  // or with ES2016 object spread
  return { ...user, isActivated: true };
}

我们可以将这些用户对象视为不可变的(freeze 如果你愿意的话)。然后您可以修改激活器代码以使其更具功能性。

activator(user) {
  return () => {
    this.setState({ user: activate(user) });
  }
}

现在,当您单击激活按钮时,我们会使用新对象更新组件的状态,而旧对象可以自由地进行垃圾回收。

关于javascript - 如果不鼓励使用 forceUpdate(),组件应该如何对模型中的更改事件使用react?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35617580/

相关文章:

javascript - 如何在reactjs中遍历key-value

javascript - 教 children 用 Javascript 编程的书籍

android - React Native Scrollview 模拟 Android

javascript - react 错误 : You may need an appropriate loader to handle this file type

javascript - easyautocomplete 基本搜索

javascript - 如何将 Prop 从父级传递给子级 css 属性?

javascript - 如何在 ReactJS 中路由到不同的组件

javascript - 将应用程序从 Angular 5 更新到 Angular 8 会导致样式问题

javascript - firebase简单登录教程缺少用户

javascript - Angular 中的双重定义注入(inject)模块