我试图将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方法调用它们。这可能吗?
请让我澄清是否不清楚;我觉得我已经对此有点了,而我却忘记了什么才有意义。
答案 0 :(得分:0)
正如Ted所指出的,ExampleUtilities没有理由扩展React.Component
。没有任何理由要上课。我同意Andy的观点,即在这样的实用程序函数中调用setState
很奇怪,尽管几个月后(如果您不想使用Alpha),您可以使用钩子在其中做一个有状态的实用程序。更清洁的方式
下面是一个基于您的代码的示例,该示例显示了以三种不同方式管理状态:
setState
代码如下:
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,您可以在其中试用: