这是否被认为是来自高阶组件的突变?
Is this considered mutation from a Higher Order Component?
我正在阅读有关 不要改变原始组件的部分。使用 link.
中的 Composition
https://reactjs.org/docs/higher-order-components.html
然后我查看了我正在尝试构建的项目。在高层次上,这就是我的代码的样子:
class Wrapper extends Component {
constructor(props) {
this.wrappedComponent = props.wrappedComponent;
}
async componentWillAppear(cb) {
await this.wrappedComponent.prototype.fetchAllData();
/* use Greensock library to do some really fancy animation on the wrapper <Animated.div> */
this.wrappedComponent.prototype.animateContent();
cb();
}
render() {
<Animated.div>
<this.wrappedComponent {...this.props} />
</Animated.div>
}
}
class Home extends Component {
async fetchAllData(){
const [r1,r2] = await Promise.All([
fetch('http://project-api.com/endpoint1'),
fetch('http://project-api.com/endpoint2')
]);
this.setState({r1,r2});
}
animateContent(){
/* Use the GreenSock library to do fancy animation in the contents of <div id="result"> */
}
render() {
if(!this.state)
return <div>Loading...</div>;
return (
<div id="result">
{this.state.r1.contentHTML}
</div>
);
}
}
export default class App extends Component {
render() {
return <Wrapper wrappedComponent={Home} />;
}
}
我的问题是:
- 在我的
Wrapper.componentWillAppear()
中,我触发了像 this.wrappedComponent.prototype.<methodname>
这样的对象方法。这些对象方法可以设置它自己的状态或在渲染函数中为 html 的内容设置动画。这是否被视为改变原始组件?
- 如果问题 1 的答案是肯定的,那么我可能需要更好的设计 pattern/approach 来完成我在代码中尝试描述的内容。这基本上是我的大部分组件需要获取自己的数据 (
Home.fetchAllData(){then set the state()}
),更新视图 (Home.render()
),运行 一些通用动画函数 (Wrapper.componentWillAppear(){this.animateFunctionOfSomeKind()}
),然后 运行 特定于自身的动画 (Home.animateContent()
)。所以也许用抽象方法继承更适合我想做的事情?
我可能真的会写一个实际的高阶组件。而不仅仅是一个组件,它采用一个作为组件的道具(这是您在示例中所做的)。主要是因为我认为您实现它的方式有点代码味道/反模式。
也许是这样的。
class MyComponent extends React.Component {
constructor() {
super();
this.animateContent = this.animateContent.bind(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.r1 !== nextProps.r1) {
this.animateContent();
}
}
componentDidMount() {
// do your fetching and state setting here
}
animateContent() {
// do something
}
render() {
if(!this.props.r1) {
return <div>Loading...</div>;
}
return (
<div id="result">
{this.props.r1.title}
</div>
);
}
}
const myHOC = asyncFn => WrappedComponent => {
return class EnhancedComponent extends React.Component {
async componentDidMount(){
const [r1, r2] = await asyncFn();
this.setState({ r1, r2 })
this.animateContent();
}
animateContent = () => {
// do some animating for the wrapper.
}
render() {
return (<WrappedComponent {...this.props} {...this.state} />)
}
}
}
const anAsyncExample = async () => {
const result = await fetch("https://jsonplaceholder.typicode.com/posts");
return await result.json();
}
const MyEnhancedComponent = myHOC(anAsyncExample)(MyComponent);
这是一个有效的 JSFiddle,因此您可以看到它的使用情况:
https://jsfiddle.net/patrickgordon/69z2wepo/96520/
基本上我在这里所做的是创建一个 HOC(只是一个函数),它接受一个异步函数和 returns 另一个接受一个组件的函数。它将调用该函数并将第一个和第二个结果分配给 state,然后将其作为 props 传递给包装的组件。它遵循本文的原则:https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e
我正在阅读有关 不要改变原始组件的部分。使用 link.
中的 Compositionhttps://reactjs.org/docs/higher-order-components.html
然后我查看了我正在尝试构建的项目。在高层次上,这就是我的代码的样子:
class Wrapper extends Component {
constructor(props) {
this.wrappedComponent = props.wrappedComponent;
}
async componentWillAppear(cb) {
await this.wrappedComponent.prototype.fetchAllData();
/* use Greensock library to do some really fancy animation on the wrapper <Animated.div> */
this.wrappedComponent.prototype.animateContent();
cb();
}
render() {
<Animated.div>
<this.wrappedComponent {...this.props} />
</Animated.div>
}
}
class Home extends Component {
async fetchAllData(){
const [r1,r2] = await Promise.All([
fetch('http://project-api.com/endpoint1'),
fetch('http://project-api.com/endpoint2')
]);
this.setState({r1,r2});
}
animateContent(){
/* Use the GreenSock library to do fancy animation in the contents of <div id="result"> */
}
render() {
if(!this.state)
return <div>Loading...</div>;
return (
<div id="result">
{this.state.r1.contentHTML}
</div>
);
}
}
export default class App extends Component {
render() {
return <Wrapper wrappedComponent={Home} />;
}
}
我的问题是:
- 在我的
Wrapper.componentWillAppear()
中,我触发了像this.wrappedComponent.prototype.<methodname>
这样的对象方法。这些对象方法可以设置它自己的状态或在渲染函数中为 html 的内容设置动画。这是否被视为改变原始组件? - 如果问题 1 的答案是肯定的,那么我可能需要更好的设计 pattern/approach 来完成我在代码中尝试描述的内容。这基本上是我的大部分组件需要获取自己的数据 (
Home.fetchAllData(){then set the state()}
),更新视图 (Home.render()
),运行 一些通用动画函数 (Wrapper.componentWillAppear(){this.animateFunctionOfSomeKind()}
),然后 运行 特定于自身的动画 (Home.animateContent()
)。所以也许用抽象方法继承更适合我想做的事情?
我可能真的会写一个实际的高阶组件。而不仅仅是一个组件,它采用一个作为组件的道具(这是您在示例中所做的)。主要是因为我认为您实现它的方式有点代码味道/反模式。
也许是这样的。
class MyComponent extends React.Component {
constructor() {
super();
this.animateContent = this.animateContent.bind(this);
}
componentWillReceiveProps(nextProps) {
if (this.props.r1 !== nextProps.r1) {
this.animateContent();
}
}
componentDidMount() {
// do your fetching and state setting here
}
animateContent() {
// do something
}
render() {
if(!this.props.r1) {
return <div>Loading...</div>;
}
return (
<div id="result">
{this.props.r1.title}
</div>
);
}
}
const myHOC = asyncFn => WrappedComponent => {
return class EnhancedComponent extends React.Component {
async componentDidMount(){
const [r1, r2] = await asyncFn();
this.setState({ r1, r2 })
this.animateContent();
}
animateContent = () => {
// do some animating for the wrapper.
}
render() {
return (<WrappedComponent {...this.props} {...this.state} />)
}
}
}
const anAsyncExample = async () => {
const result = await fetch("https://jsonplaceholder.typicode.com/posts");
return await result.json();
}
const MyEnhancedComponent = myHOC(anAsyncExample)(MyComponent);
这是一个有效的 JSFiddle,因此您可以看到它的使用情况: https://jsfiddle.net/patrickgordon/69z2wepo/96520/
基本上我在这里所做的是创建一个 HOC(只是一个函数),它接受一个异步函数和 returns 另一个接受一个组件的函数。它将调用该函数并将第一个和第二个结果分配给 state,然后将其作为 props 传递给包装的组件。它遵循本文的原则:https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e