简体   繁体   English

反应无状态功能组件和组件生命周期

[英]React stateless functional components and component lifecycle

So I just switched to using stateless functional components in React with Redux and I was curious about component lifecycle. 所以我只是转而使用React中的 无状态功能组件Redux ,我对组件生命周期感到好奇。 Initially I had this : 最初我有这个:

// actions.js

export function fetchUser() {
    return {
        type: 'FETCH_USER_FULFILLED',
        payload: {
            name: 'username',
            career: 'Programmer'
        }
    }
}

Then in the component I used a componentDidMount to fetch the data like so : 然后在组件中我使用componentDidMount来获取数据,如下所示:

// component.js

...
componentDidMount() {
  this.props.fetchUser()
}
...

After switching to stateless functional components I now have a container with : 切换到无状态功能组件后,我现在有一个容器:

// statelessComponentContainer.js

...
const mapStateToProps = state => {
  return {
    user: fetchUser().payload
  }
}
...

As you can see, currently I am not fetching any data asynchronously. 如您所见,目前我不是异步获取任何数据。 So my question is will this approach cause problems when I start fetching data asynchronously? 所以我的问题是,当我开始异步获取数据时,这种方法会导致问题吗? And also is there a better approach? 还有更好的方法吗?

I checked out this blog , where they say If your components need lifecycle methods, use ES6 classes . 我查看了这个博客 ,他们说如果您的组件需要生命周期方法,请使用ES6类 Any assistance will be appreciated. 任何帮助将不胜感激。

Firstly, don't do what you are trying to to do in mapStateToProps . 首先,不要在mapStateToProps执行您要执行的mapStateToProps Redux follows a unidirectional data flow pattern, where by component dispatch action, which update state, which changes component. Redux遵循单向数据流模式,其中通过组件调度操作,更新状态,更改组件。 You should not expect your action to return the data, but rather expect the store to update with new data. 您不应期望您的操作返回数据,而是期望商店使用新数据进行更新。

Following this approach, especially once you are fetching the data asynchronously, means you will have to cater for a state where your data has not loaded yet. 遵循这种方法,特别是在异步提取数据后,意味着您必须满足尚未加载数据的状态。 There are plenty of questions and tutorials out there for that (even in another answer in this question), so I won't worry to put an example in here for you. 有很多问题和教程(即使在这个问题的另一个答案中),所以我不会担心在这里为你举一个例子。

Secondly, wanting to fetch data asynchronously when a component mounts is a common use case. 其次,想要在组件安装时异步获取数据是一个常见的用例。 Wanting to write nice functional component is a common desire. 想要编写好的功能组件是一个共同的愿望。 Luckily, I have a library that allows you to do both: react-redux-lifecycle . 幸运的是,我有一个库可以让你做到这两点react-redux-lifecycle

Now you can write: 现在你可以写:

import { onComponentDidMount } from 'react-redux-lifecycle'
import { fetchUser } from './actions'

const User = ({ user }) => {
   return // ...
}

cont mapStateToProps = (state) => ({
  user = state.user
})

export default connect(mapStateToProps)(onComponentDidMount(fetchUser)(User))

I have made a few assumptions about your component names and store structure, but I hope it is enough to get the idea across. 我已经对您的组件名称和存储结构做了一些假设,但我希望它足以让我们了解这个想法。 I'm happy to clarify anything for you. 我很高兴为您澄清任何事情。

Disclaimer: I am the author of react-redux-lifecycle library. 免责声明:我是react-redux-lifecycle library的作者。

Don't render any view if there is no data yet. 如果还没有数据,请不要渲染任何视图。 Here is how you do this. 这是你如何做到这一点。

Approach of solving your problem is to return a promise from this.props.fetchUser() . 解决问题的方法是从this.props.fetchUser()返回一个promise You need to dispatch your action using react-thunk (See examples and information how to setup. It is easy!) . 您需要使用react-thunk dispatch您的操作(请参阅示例和信息如何设置。这很简单!)

Your fetchUser action should look like this: 您的fetchUser操作应如下所示:

export function fetchUser() {
  return (dispatch, getState) => {
      return new Promise(resolve => {
          resolve(dispatch({         
          type: 'FETCH_USER_FULFILLED',
          payload: {
            name: 'username',
            career: 'Programmer'
          }
        }))
      });
  };
}

Then in your Component add to lifecycle method componentWillMount() following code: 然后在您的Component添加生命周期方法componentWillMount()以下代码:

componentDidMount() {
  this.props.fetchUser()
    .then(() => {
      this.setState({ isLoading: false });
    })
}

Of course your class constructor should have initial state isLoading set to true . 当然,您的类constructor应该将初始状态isLoading设置为true

constructor(props) {
  super(props);

  // ...

  this.state({
    isLoading: true
  })
}

Finally in your render() method add a condition. 最后在render()方法中添加一个条件。 If your request is not yet completed and we don't have data, print 'data is still loading...' otherwise show <UserProfile /> Component. 如果您的请求尚未完成且我们没有数据,则打印'数据仍在加载...',否则显示<UserProfile /> Component。

render() {
  const { isLoading } = this.state;

  return (
    <div>{ !isLoading ? <UserProfile /> : 'data is still loading...' }</div>
  )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM