Last active
May 28, 2019 15:42
-
-
Save mattpocock/de1b1982dc86ebfa91af78fd3ab6cd61 to your computer and use it in GitHub Desktop.
withFluxStore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Composes single-argument functions from right to left. The rightmost | |
| * function can take multiple arguments as it provides the signature for | |
| * the resulting composite function. | |
| * | |
| * @param {...Function} funcs The functions to compose. | |
| * @returns {Function} A function obtained by composing the argument functions | |
| * from right to left. For example, compose(f, g, h) is identical to doing | |
| * (...args) => f(g(h(...args))). | |
| */ | |
| export default function compose(...funcs) { | |
| if (funcs.length === 0) { | |
| return arg => arg | |
| } | |
| if (funcs.length === 1) { | |
| return funcs[0] | |
| } | |
| return funcs.reduce((a, b) => (...args) => a(b(...args))) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // React | |
| import React from 'react' | |
| import { Localisation } from 'javascript/config/features' | |
| // Stores | |
| import PagesStore from 'javascript/stores/pages' | |
| // Actions | |
| import PagesActions from 'javascript/actions/pages' | |
| // Components | |
| import PageLoader from 'javascript/components/page-loader' | |
| import Blocks from 'javascript/views/blocks' | |
| import Meta from 'react-document-meta' | |
| import ListModal from 'javascript/components/list-modal' | |
| import Modal from 'javascript/components/modal' | |
| import compose from 'javascript/utils/compose'; | |
| import withPageHelper from 'javascript/utils/withPageHelper'; | |
| import withFluxStore from 'javascript/utils/withFluxStore'; | |
| class Home extends React.Component { | |
| constructor(props) { | |
| super(props) | |
| this.state = { | |
| modal: () => { } | |
| } | |
| } | |
| componentDidMount() { | |
| PagesActions.getResources({ | |
| include: 'page-images,meta-datum', | |
| fields: { | |
| 'page-images': 'file,filename', | |
| 'pages': 'content-blocks,page-images,meta-datum', | |
| 'meta-datums': 'title,keywords,description' | |
| }, | |
| filter: { | |
| slug: Localisation.home.lower | |
| } | |
| }) | |
| } | |
| addToList = (resource) => () => { | |
| this.setState(() => ({ | |
| modal: () => ( | |
| <Modal delay={500} ref="modal" customContent={true} modifiers={['custom-content']}> | |
| <ListModal resource={resource} closeEvent={this.unsetModal} user={this.props.user} /> | |
| </Modal> | |
| ) | |
| })) | |
| return false | |
| } | |
| render() { | |
| const { pageLoadState, resource = {} } = this.props; | |
| return ( | |
| <Meta | |
| title={resource['meta-datum'] && resource['meta-datum'].title || resource.title} | |
| meta={{ | |
| description: resource['meta-datum'] && resource['meta-datum'].description || '', | |
| keywords: resource['meta-datum'] && resource['meta-datum'].keywords || '' | |
| }}> | |
| <PageLoader {...pageLoadState}> | |
| <main> | |
| <div className="fade-on-load"> | |
| {(resource['content-blocks'] || []).map((block) => { | |
| const bgImage = block.bgImage ? resource['page-images'].find(i => i.id === block.bgImage.id) : null | |
| return ( | |
| /* #region ae | banijay | cineflix | demo | drg | itv | keshet | rtv | sky */ | |
| <section key={block.id} className={[block.type !== 'banner-carousel' && 'content-block', block.type, block.background].join(' content-block--')} style={block.background === 'image' && bgImage ? { | |
| backgroundImage: `url(${bgImage.file.url.replace('.net/', '.net/1600x600/')})`, | |
| /* #region itv */ | |
| backgroundSize: 'cover' | |
| /* #endregion */ | |
| } : null}> | |
| /* #endregion */</section> | |
| /* #region amc */ | |
| <section key={block.id} className={[block.type !== 'banner-carousel' && 'content-block', block.type, block.background, block.fullWidth && 'full'].join(' content-block--')} style={block.background === 'image' && bgImage ? { | |
| backgroundImage: `url(${bgImage.file.url.replace('.net/', '.net/1600x600/')})` | |
| } : null}> | |
| /* #endregion */ </section> | |
| /* #region all3 */ | |
| <section key={block.id} className={[block.type !== 'banner-carousel' && 'content-block', block.type, block.background].join(' content-block--')} > | |
| {block.background === 'image' && bgImage && ( | |
| <img className="content-block__bg-image" src={bgImage.file.url.replace('.net/', '.net/1600x600/')} /> | |
| )} | |
| /* #endregion */ | |
| <div className={(block.type !== 'html-markup' && block.type !== 'banner-carousel' && block.type !== 'promo-carousel' && block.type !== 'text-and-items' && block.type !== 'related-pages') ? 'container' : 'content-block__inner'}> | |
| {Blocks(block, { | |
| 'page-images': resource['page-images'] | |
| }, { user: this.props.user, addToList: this.addToList })} | |
| </div> | |
| </section> | |
| ) | |
| })} | |
| </div> | |
| /* #region ae | all3 | banijay | cineflix | demo | drg | itv | keshet | rtv | sky */ | |
| {this.state.modal()} | |
| /* #endregion */ | |
| </main> | |
| </PageLoader> | |
| </Meta> | |
| ) | |
| } | |
| } | |
| export default compose( | |
| withPageHelper, | |
| withFluxStore({ | |
| store: PagesStore, | |
| changeEventKey: 'change', | |
| handleChange: ({ store, setPassedDownProps, props }) => { | |
| const resource = store.getResources()[0] | |
| if (resource) { | |
| setPassedDownProps({ resource }) | |
| props.finishedLoading() | |
| } | |
| } | |
| }), | |
| )(Home) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, { useEffect, useState } from 'react' | |
| const withFluxStore = ({ | |
| store, | |
| changeEventKey, | |
| handleChange | |
| }) => Component => props => { | |
| const [hasConnected, setHasConnected] = useState(false) | |
| const [passedDownProps, setPassedDownProps] = useState({}) | |
| const callHandleChangeCallback = () => { | |
| handleChange({ store, props, setPassedDownProps }) | |
| } | |
| useEffect(() => { | |
| store.on(changeEventKey, callHandleChangeCallback) | |
| setHasConnected(true) | |
| return () => { | |
| if (store.removeEventListener) { | |
| store.removeEventListener(changeEventKey, callHandleChangeCallback) | |
| } | |
| } | |
| }, []) | |
| if (!hasConnected) { | |
| return null | |
| } | |
| return <Component {...props} {...passedDownProps} /> | |
| } | |
| export default withFluxStore |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React from 'react' | |
| import { useState } from 'react' | |
| const withPageHelper = Component => props => { | |
| const [errored, setErrored] = useState(false) | |
| const [loaded, setLoaded] = useState(false) | |
| const receivedError = () => { | |
| setErrored(true) | |
| } | |
| const finishedLoading = () => { | |
| setLoaded(true) | |
| } | |
| return ( | |
| <Component | |
| {...props} | |
| finishedLoading={finishedLoading} | |
| receivedError={receivedError} | |
| pageLoadState={{ errored, loaded }} | |
| /> | |
| ) | |
| } | |
| export default withPageHelper |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment