I have this class component and want to rewrite it to stateless functional component with 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
})
})
}
I'm struggling to combine onSelectLanguage
and onFetchRepos
in one function as in my code before refactoring. I don't know how to rewrite this for my componentDidMount function as well.
got this working with:
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
})
})
}
}
})
)
These lifecycles don't look very sexy though. Not sure if this worth refactoring.
Extending on the previous answer, you could use functional composition to combine the onFetchRepos
and onSelectLanguage
as required.
If I understand your requirements correctly, you should be able to achieve this by the following:
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
})
})
})
}
})
)
Hope this helps you!