反应:如何使私有方法绑定到相对组件?

时间:2018-12-31 18:33:21

标签: reactjs

我试图将React组件用作实用程序类,其中包含将更新另一个(视图)组件状态的方法。

问题是,当我将实用程序方法绑定到视图组件时,该实用程序方法调用的私有方法似乎无法访问,并且出现错误TypeError: this._filterForCurrentlySelectedTimeRange is not a function

我尝试过: 1.将私有方法保留在视图组件中(显然,这是可行的。) 2.以各种方式将私有方法绑定到实用程序组件。

我的代码当前类似于:

utilities.jsx

class ExampleUtilities extends React.Component {
    constructor(props) {
        this.capitalizeFirstChar = this.privateMethod.bind(this);
    }

    static capitalize(word) {
       const result = this._capitalizeFirstChar(word);
       this.setState({ capitalizedWord: result })
    }

    _capitalizeFirstChar(word) {
        return word.charAt(0).toUpperCase();
    }
}
export default ExampleUtilities;

view.jsx

import ExampleUtilities from '../components/utilities';

class View extends React.Component {
    constructor(props) {
        super(props);
        this.state = { capitalizedWord: null }
    }

    render() {
        return( 
            <input type="input" onChange={event =>  
    ExampleUtilities.capitalize.bind(this, event.target.value)}</input>
        )
    }
}

理想情况下,我可以将私有方法保留在Utility类内,并使用Utility方法调用它们。这可能吗?

请让我澄清是否不清楚;我觉得我已经对此有点了,而我却忘记了什么才有意义。

1 个答案:

答案 0 :(得分:0)

正如Ted所指出的,ExampleUtilities没有理由扩展React.Component。没有任何理由要上课。我同意Andy的观点,即在这样的实用程序函数中调用setState很奇怪,尽管几个月后(如果您不想使用Alpha),您可以使用钩子在其中做一个有状态的实用程序。更清洁的方式 下面是一个基于您的代码的示例,该示例显示了以三种不同方式管理状态:

  • 第一个(View.js)与您使用绑定实用程序方法调用setState
  • 的最相似。
  • 第二个(View2.js)使用更简单的实用程序,并将状态管理保留在其自己的组件中
  • 第三个(HooksView.js)显示了在React的alpha版本中如何使用钩子来封装它并摆脱所有类的样板

代码如下:

index.js

import React from "react";
import ReactDOM from "react-dom";
import View from "./View";
import View2 from "./View2";
import HooksView from "./HooksView";

function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <View />
      <br />
      <View2 />
      <br />
      <HooksView />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

utilities.js

import { useState } from "react";

// must be bound
export const capitalizeFirstCharAndSetState = function(word) {
  const result = privateCapitalizeFirstChar(word);
  this.setState({ capitalizedWord: result });
};
export const capitalizeFirstChar = word => {
  return privateCapitalizeFirstChar(word);
};
// not exported
const privateCapitalizeFirstChar = word =>
  word.charAt(0).toUpperCase() + word.substr(1);

export const useCapitalizedChangeHandler = () => {
  const [word, setWord] = useState("");
  const setCapitalizedWord = event => {
    const capitalized = privateCapitalizeFirstChar(event.target.value);
    setWord(capitalized);
  };
  return [word, setCapitalizedWord];
};

View.js

import React from "react";
import { capitalizeFirstCharAndSetState } from "./utilities";

class View extends React.Component {
  constructor(props) {
    super(props);
    this.state = { capitalizedWord: "" };
    this.changeHandler1 = capitalizeFirstCharAndSetState.bind(this);
  }

  render() {
    return (
      <input
        type="input"
        value={this.state.capitalizedWord}
        onChange={event => this.changeHandler1(event.target.value)}
      />
    );
  }
}
export default View;

View2.js

import React from "react";
import { capitalizeFirstChar } from "./utilities";

class View2 extends React.Component {
  constructor(props) {
    super(props);
    this.state = { capitalizedWord: "" };
    this.changeHandler2 = event => {
      this.setState({
        capitalizedWord2: capitalizeFirstChar(event.target.value)
      });
    };
  }

  render() {
    return (
      <input
        type="input"
        value={this.state.capitalizedWord2}
        onChange={this.changeHandler2}
      />
    );
  }
}
export default View2;

HooksView.js

import React, { useState } from "react";
import { useCapitalizedChangeHandler } from "./utilities";

const HooksView = () => {
  const [word, setWord] = useCapitalizedChangeHandler();
  return <input type="input" value={word} onChange={setWord} />;
};
export default HooksView;

这是一个CodeSandbox,您可以在其中试用:

Edit pmw8v2184j