taskrabbit/react-component-extension

语言: JavaScript

git: https://github.com/taskrabbit/react-component-extension

命名空间高阶组件
Namespaced Higher Order Components
README.md (中文)

由于mixins已经死了,更高阶的组件是要走的路。

但是,当您为组件使用多个更高阶的组件时,它可能会令人困惑,您必须考虑行为的来源。

Extension是命名空间,并且还明确说明要提供给Component的方法/变量是什么。

要创建扩展:

这里我们定义了一个UserConnection扩展,它允许获取它允许你在组件中调用的用户信息,this.props ['UserConnection']。variabless.firstName和this.props ['UserConnection']。variables.lastName。 如果要刷新用户,只需调用this.props ['UserConnection']。refresh()。 您可以将accountUrl和updateAccountUrl作为Extension的params传递。

import * as Extension from 'react-component-extension';

const UserConnection = {
  // This is the public name of the Extension
  extensionName: 'UserConnection',
  exports: {
    // Variables accessibles from the Extension
    variables: ['firstName', 'lastName'],
    // Methods callable on the Extension
    methods: ['refresh'],
  },
  // Required params to use the extension
  // should be an object key: 'description'
  requiredParams: {
    accountUrl: 'url to fetch the user',
  },
  optionalParams: {
    updateAccountUrl: 'url to update the user',
  },
}

export default Extension.create(UserConnection);

要使用扩展名:

class Account extends React.Component {
  render() {
    <div>
      hello {this.props['UserConnection'].variables.firstName}
      click <button onClick={this.props['UserConnection'].refresh}>here</button> to refresh
    </div>
  }
}

export default UserConnection(AccountPage, {
  accountUrl: 'api/account'
});

其他例子

const AddSpinningLoader = {
  extensionName: 'AddSpinningLoader',

  exports: {
    methods: ['start', 'stop']
  },

  getInitialState() {
    return {
      loading: false,
    }
  },

  start() {
    this.setState({loading: true})
  },

  stop() {
    this.setState({loading: false})
  },

  renderExtension() {
    let spinningLoader = this.state.loading ? <SpinningLoader/> : null;

    return (
      <div>
        {spinningLoarder}
        {this.renderComponent()}
      </div>
    )
  }  
};

export default Extension.create(AddSpinningLoader);
@AddSpinningLoader
class Form extends React.Component {
  constructor(props) {
    super(props);

    this.onSubmitButton = this.onSubmitButton.bind(this);

    this.state = {
      firstName: ''
    };
  }

  onSubmitButton() {
    this.props['ValidationErrorBar'].validateOrShowBar().then(
      this.doAccountUpdate
    );
  }

  doAccountUpdate() {
    this.props['AddSpinningLoader'].start();

    $.post('api/account_update', {
      firstName: this.state.firstName
    }).then(
      this.props['AddSpinningLoader'].stop
    );
  }

  render() {
    <div>
      <input type="text" value={this.state.firstName} onChange={(firstName) => this.setState({firstName})} />;
      <button onClick={this.onSubmitButton} />
    </div>
  }
}

Form = ValidationErrorBar(Form, {
  isValid: function () {
    return this.firstName !== '';
  },
});

export default Form;

安装

npm install --save react-component-extension

从React Mixin更新到扩展

将React Mixin作为扩展是非常简单的,例如这里是react-timer-mixin作为扩展

ALL

  • 添加测试
  • 真的做了示例代码
  • 添加示例

本文使用googletrans自动翻译,仅供参考, 原文来自github.com

en_README.md

Since mixins are dead, higher order components are the way to go.

But when you use multiple higher order component for a Component it can be confusing, you have to think about where the behavior comes from.

An Extension is namespaced and also explicit about what are the methods/variables that are be provided to the Component.

To create an Extension:

Here we are defining a UserConnection extension, it allows to get the user information it allows you to call in your component, this.props['UserConnection'].variables.firstName and this.props['UserConnection'].variables.lastName.
If you want to refresh the user simply call this.props['UserConnection'].refresh().
You can pass accountUrl and updateAccountUrl as params of the Extension.

import * as Extension from 'react-component-extension';

const UserConnection = {
  // This is the public name of the Extension
  extensionName: 'UserConnection',
  exports: {
    // Variables accessibles from the Extension
    variables: ['firstName', 'lastName'],
    // Methods callable on the Extension
    methods: ['refresh'],
  },
  // Required params to use the extension
  // should be an object key: 'description'
  requiredParams: {
    accountUrl: 'url to fetch the user',
  },
  optionalParams: {
    updateAccountUrl: 'url to update the user',
  },
}

export default Extension.create(UserConnection);

To use the Extension:

class Account extends React.Component {
  render() {
    <div>
      hello {this.props['UserConnection'].variables.firstName}
      click <button onClick={this.props['UserConnection'].refresh}>here</button> to refresh
    </div>
  }
}

export default UserConnection(AccountPage, {
  accountUrl: 'api/account'
});

Other Examples

const AddSpinningLoader = {
  extensionName: 'AddSpinningLoader',

  exports: {
    methods: ['start', 'stop']
  },

  getInitialState() {
    return {
      loading: false,
    }
  },

  start() {
    this.setState({loading: true})
  },

  stop() {
    this.setState({loading: false})
  },

  renderExtension() {
    let spinningLoader = this.state.loading ? <SpinningLoader/> : null;

    return (
      <div>
        {spinningLoarder}
        {this.renderComponent()}
      </div>
    )
  }  
};

export default Extension.create(AddSpinningLoader);
@AddSpinningLoader
class Form extends React.Component {
  constructor(props) {
    super(props);

    this.onSubmitButton = this.onSubmitButton.bind(this);

    this.state = {
      firstName: ''
    };
  }

  onSubmitButton() {
    this.props['ValidationErrorBar'].validateOrShowBar().then(
      this.doAccountUpdate
    );
  }

  doAccountUpdate() {
    this.props['AddSpinningLoader'].start();

    $.post('api/account_update', {
      firstName: this.state.firstName
    }).then(
      this.props['AddSpinningLoader'].stop
    );
  }

  render() {
    <div>
      <input type="text" value={this.state.firstName} onChange={(firstName) => this.setState({firstName})} />;
      <button onClick={this.onSubmitButton} />
    </div>
  }
}

Form = ValidationErrorBar(Form, {
  isValid: function () {
    return this.firstName !== '';
  },
});

export default Form;

Install

npm install --save react-component-extension

Updating from a React Mixin to an Extension

It is pretty straightforward to make a React Mixin an Extension, for example here is react-timer-mixin as an Extension

TODO

  • Add tests
  • Really do the example code
  • Add examples