如何使用“ recompose”来重写它?

时间:2018-09-03 00:31:13

标签: reactjs recompose

我有这个类组件,想用recompose将其重写为无状态功能组件:

export default class Popular extends Component {
    state = {
        value: 0,
        selected: "All",
        repos: null
    }

componentDidMount() {
    this.handleSelected(this.state.selected)
}

handleChange = (e, value) => {
    this.setState({ value })
}

handleSelected = lang => {
    this.setState({
        selected: lang,
        repos: null
    })
    fetchPopularRepos(lang).then(repos => {
        this.setState({
            selected: lang,
            repos
        })
    })
}

在重构之前,我正努力将onSelectLanguageonFetchRepos结合到我的代码中的一个函数中。我也不知道该如何为我的componentDidMount函数重写它。

更新:

通过以下方式获得了这种帮助

const enhance = compose(
  withStateHandlers(initialState, {
    onChangeLanguage,
    onSelectLanguage
  }),
  lifecycle({
    componentDidMount() {
      fetchPopularRepos(this.props.selected).then(repos => {
        this.setState({
          repos
        })
      })
    }
  }),
  lifecycle({
    componentDidUpdate(prevProps) {
      if (this.props.selected !== prevProps.selected) {
        this.setState({ repos: null })
        fetchPopularRepos(this.props.selected).then(repos => {
          this.setState({
            repos
          })
        })
      }
    }
  })
)

这些生命周期看起来并不十分性感。不知道这是否值得重构。

2 个答案:

答案 0 :(得分:1)

这似乎是您要使用the lifecycle() method的情况。我不是recompose专家,但是我认为以下调整可能会实现您的目标:

const onFetchPopularRepos = props => () => {
    // Make sure the method returns the promise
    return fetchPopularRepos(props.selected).then(repos => ({  
        repos: repos
    }))
}

const withPopularReposState = withStateHandlers(initialState, {
    onChangeLanguage,
    onSelectLanguage
})

// Add a life cycle hook to fetch data on mount
const withLifecycle = lifecycle({
  componentDidMount() {

    // Update the state
    onFetchPopularRepos(this.props).then(newState => this.setState(newState)) 
  }
})();

// Compose the functional component with both lifecycle HOC
const enhance = withLifecycle(withPopularReposState)

答案 1 :(得分:0)

在上一个答案的基础上,您可以根据需要使用功能组合来组合onFetchReposonSelectLanguage。 如果我正确理解您的要求,则应该可以通过以下方法实现这一目标:

const initialState = {
    value: 0,
    selected: "All",
    repos: null
}

const onChangeLanguage = props => (event, value) => ({
    value
})

const onSelectLanguage = props => lang => ({
    selected: lang
})

const onFetchRepos = props => (fetchPopularRepos(props.selected).then(repos => ({
    repos
})))

// Combined function: onFetchRepos followed by call to onSelectLanguage
const onFetchReposWithSelectLanguage = props => onFetchRepos(props)
      .then(response => props.onSelectLanguage(response))

// Minimal code to compose a functional component with both state handers and 
// lifecycle handlers
const enhance = compose(
    withStateHandlers(initialState, {
        onChangeLanguage,
        onSelectLanguage
    }),
    lifecycle({
        componentDidMount() {
            // Fetch repos and select lang on mount
            onFetchReposWithSelectLanguage(this.props)
        }
    })
)

更新

// Minimal code to compose a functional component with both state handers and 
// lifecycle handlers
const enhance = compose(
    withStateHandlers(initialState, {
        onChangeLanguage,
        onSelectLanguage,
        setRepos
    }),
    lifecycle({
        componentDidMount() {
            // Reuse onSelectLanguage logic and call setState manually, use setState callback that
            // fires after state is updated to trigger fetch based on newState.selected language
            this.setState(onSelectLanguage(this.props.selected)(this.props), newState => {
                fetchPopularRepos(newState.selected).then(repos => {
                    this.setState({
                        repos
                    })
                })
            })
        }
    })
)

希望这对您有帮助!