使用高阶组件时绑定 onClick
Bind onClick when using higher order component
可能是个新问题。我是新来的反应。
关注一些博客 post 之类的,我能够构建一个包含高阶组件的页面和 componentDidMount
从 API 加载数据并将其呈现到页面.它工作得很好,代码看起来很干净,但我不知道如何通过高阶组件传递某种 onClick,最终我想将获取的内容移动到一个可以调用的函数中componentDidMount
和 <Button onClick={}>Reload</Button>
。请打住
import React, { Component } from 'react';
import {Button, CardColumns, Card, CardHeader, CardBody} from 'reactstrap';
const API = 'http://localhost:3000/';
const DEFAULT_QUERY = 'endpoint';
const withFetching = (url) => (Comp) =>
class WithFetching extends Component {
constructor(props) {
super(props);
this.state = {
data: {},
isLoading: false,
error: null,
};
// Goes here?
this.onClick = () => {
console.log("Handled!");
};
}
componentDidMount() {
this.setState({ isLoading: true });
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
// Or here maybe??
this.onClick = () => {
console.log("Handled!");
};
render() {
// How do I pass it in?
return <Comp { ...this.props } { ...this.state } onClick={this.onClick} />
}
}
// How do I tell this component to expect it to recieve the handler?
const App = ({ data, isLoading, error }) => {
const hits = data.hits || [];
console.log(data);
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="animated fadeIn">
<CardColumns className="cols-2">
<Card>
<CardHeader>
API Card!
<div className="card-actions">
</div>
</CardHeader>
<CardBody>
{hits.map(hit =>
<div key={hit.foo}>
<h3>{hit.foo}</h3>
_____
</div>
)}
<Button onClick={props.onClick}>Launch demo modal</Button>
</CardBody>
</Card>
</CardColumns>
</div>
);
}
export default withFetching(API + DEFAULT_QUERY)(App);
Here 是博客 post 引导我找到我正在使用的架构:
编辑:我可以在 class 之外创建一个函数,以便它在任何地方都可用,但我最初想将它留在 中 的原因是我实际上可以改变状态并用新数据重新渲染卡片。试图找出 bind()
的正确用法来完成这项工作...... JS 有时让我觉得很愚蠢 :p
您是否考虑过将该函数设为所有 类 之外的根级函数?然后任何组件都可以调用它。
例如:
import React, { Component } from 'react';
import {Button, CardColumns, Card, CardHeader, CardBody} from 'reactstrap';
const API = 'http://localhost:3000/';
const DEFAULT_QUERY = 'endpoint';
function sharedUtilityFunction(){
// Do something here
}
const withFetching = (url) => (Comp) =>
class WithFetching extends Component {
constructor(props) {
super(props);
this.state = {
data: {},
isLoading: false,
error: null,
};
}
componentDidMount() {
sharedUtilityFunction();
this.setState({ isLoading: true });
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
return <Comp { ...this.props } { ...this.state } />
}
}
// How do I tell this component to expect it to recieve the handler?
const App = ({ data, isLoading, error }) => {
const hits = data.hits || [];
console.log(data);
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="animated fadeIn">
<CardColumns className="cols-2">
<Card>
<CardHeader>
API Card!
<div className="card-actions">
</div>
</CardHeader>
<CardBody>
{hits.map(hit =>
<div key={hit.foo}>
<h3>{hit.foo}</h3>
_____
</div>
)}
<Button onClick={() => sharedUtilityFunction()}>Launch demo modal</Button>
</CardBody>
</Card>
</CardColumns>
</div>
);
}
export default withFetching(API + DEFAULT_QUERY)(App);
我一直在寻找的答案确实是将函数作为 prop 传递给低阶组件。为此,我需要将 compent 预期参数的方式更改为:const App = props => {
待定,无论这是否有其他影响,但我 认为 状态已经通过了prop 无论如何......正确调用函数会导致 isLoading
渲染,所以这是一个好兆头。
import React, { Component } from 'react';
import {Button, CardColumns, Card, CardHeader, CardBody} from 'reactstrap';
const API = 'http://localhost:3000/';
const DEFAULT_QUERY = 'endpoint';
const withFetching = (url) => (Comp) =>
class WithFetching extends Component {
constructor(props) {
super(props);
this.state = {
data: {},
isLoading: false,
error: null,
};
this.goFetch = this.goFetch.bind(this);
}
goFetch() {
this.setState({ isLoading: true });
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
componentDidMount() {
this.goFetch();
}
render() {
return <Comp { ...this.props } { ...this.state } goFetch={this.goFetch}/>
}
}
const App = props => {
const hits = props.data.hits || [];
if (props.error) {
return <p>{props.error.message}</p>;
}
if (props.isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="animated fadeIn">
<CardColumns className="cols-2">
<Card>
<CardHeader>
API Card!
<div className="card-actions">
</div>
</CardHeader>
<CardBody>
{hits.map((hit, index) =>
<div key={index}>
Foo: <h3>{hit.foo}</h3>
</div>
)}
<Button onClick={props.goFetch}>Refresh</Button>
</CardBody>
</Card>
</CardColumns>
</div>
);
}
export default withFetching(API + DEFAULT_QUERY)(App);
可能是个新问题。我是新来的反应。
关注一些博客 post 之类的,我能够构建一个包含高阶组件的页面和 componentDidMount
从 API 加载数据并将其呈现到页面.它工作得很好,代码看起来很干净,但我不知道如何通过高阶组件传递某种 onClick,最终我想将获取的内容移动到一个可以调用的函数中componentDidMount
和 <Button onClick={}>Reload</Button>
。请打住
import React, { Component } from 'react';
import {Button, CardColumns, Card, CardHeader, CardBody} from 'reactstrap';
const API = 'http://localhost:3000/';
const DEFAULT_QUERY = 'endpoint';
const withFetching = (url) => (Comp) =>
class WithFetching extends Component {
constructor(props) {
super(props);
this.state = {
data: {},
isLoading: false,
error: null,
};
// Goes here?
this.onClick = () => {
console.log("Handled!");
};
}
componentDidMount() {
this.setState({ isLoading: true });
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
// Or here maybe??
this.onClick = () => {
console.log("Handled!");
};
render() {
// How do I pass it in?
return <Comp { ...this.props } { ...this.state } onClick={this.onClick} />
}
}
// How do I tell this component to expect it to recieve the handler?
const App = ({ data, isLoading, error }) => {
const hits = data.hits || [];
console.log(data);
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="animated fadeIn">
<CardColumns className="cols-2">
<Card>
<CardHeader>
API Card!
<div className="card-actions">
</div>
</CardHeader>
<CardBody>
{hits.map(hit =>
<div key={hit.foo}>
<h3>{hit.foo}</h3>
_____
</div>
)}
<Button onClick={props.onClick}>Launch demo modal</Button>
</CardBody>
</Card>
</CardColumns>
</div>
);
}
export default withFetching(API + DEFAULT_QUERY)(App);
Here 是博客 post 引导我找到我正在使用的架构:
编辑:我可以在 class 之外创建一个函数,以便它在任何地方都可用,但我最初想将它留在 中 的原因是我实际上可以改变状态并用新数据重新渲染卡片。试图找出 bind()
的正确用法来完成这项工作...... JS 有时让我觉得很愚蠢 :p
您是否考虑过将该函数设为所有 类 之外的根级函数?然后任何组件都可以调用它。
例如:
import React, { Component } from 'react';
import {Button, CardColumns, Card, CardHeader, CardBody} from 'reactstrap';
const API = 'http://localhost:3000/';
const DEFAULT_QUERY = 'endpoint';
function sharedUtilityFunction(){
// Do something here
}
const withFetching = (url) => (Comp) =>
class WithFetching extends Component {
constructor(props) {
super(props);
this.state = {
data: {},
isLoading: false,
error: null,
};
}
componentDidMount() {
sharedUtilityFunction();
this.setState({ isLoading: true });
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
return <Comp { ...this.props } { ...this.state } />
}
}
// How do I tell this component to expect it to recieve the handler?
const App = ({ data, isLoading, error }) => {
const hits = data.hits || [];
console.log(data);
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="animated fadeIn">
<CardColumns className="cols-2">
<Card>
<CardHeader>
API Card!
<div className="card-actions">
</div>
</CardHeader>
<CardBody>
{hits.map(hit =>
<div key={hit.foo}>
<h3>{hit.foo}</h3>
_____
</div>
)}
<Button onClick={() => sharedUtilityFunction()}>Launch demo modal</Button>
</CardBody>
</Card>
</CardColumns>
</div>
);
}
export default withFetching(API + DEFAULT_QUERY)(App);
我一直在寻找的答案确实是将函数作为 prop 传递给低阶组件。为此,我需要将 compent 预期参数的方式更改为:const App = props => {
待定,无论这是否有其他影响,但我 认为 状态已经通过了prop 无论如何......正确调用函数会导致 isLoading
渲染,所以这是一个好兆头。
import React, { Component } from 'react';
import {Button, CardColumns, Card, CardHeader, CardBody} from 'reactstrap';
const API = 'http://localhost:3000/';
const DEFAULT_QUERY = 'endpoint';
const withFetching = (url) => (Comp) =>
class WithFetching extends Component {
constructor(props) {
super(props);
this.state = {
data: {},
isLoading: false,
error: null,
};
this.goFetch = this.goFetch.bind(this);
}
goFetch() {
this.setState({ isLoading: true });
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
componentDidMount() {
this.goFetch();
}
render() {
return <Comp { ...this.props } { ...this.state } goFetch={this.goFetch}/>
}
}
const App = props => {
const hits = props.data.hits || [];
if (props.error) {
return <p>{props.error.message}</p>;
}
if (props.isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="animated fadeIn">
<CardColumns className="cols-2">
<Card>
<CardHeader>
API Card!
<div className="card-actions">
</div>
</CardHeader>
<CardBody>
{hits.map((hit, index) =>
<div key={index}>
Foo: <h3>{hit.foo}</h3>
</div>
)}
<Button onClick={props.goFetch}>Refresh</Button>
</CardBody>
</Card>
</CardColumns>
</div>
);
}
export default withFetching(API + DEFAULT_QUERY)(App);