export class Timeline extends Component {
componentWillMount () {
this.props.fetchTimeline()
}
render () {
const { f, photos, fetchTimeline } = this.props
return (
<BoardView
photos{photos.data}
fetchStatus={photos.fetchStatus}
hasMore={photos.hasMore}
onFetchMore={() => fetchTimeline(photos.entries.length)}
/>
)
}
}
const mapStateToProps = (state, ownProps) => ({
photos: getTimelinePhotos(state)
})
export const mapDispatchToProps = (dispatch, ownProps) => ({
fetchTimeline: (skip) => dispatch(fetchTimeline(skip))
})
export default translate()(connect(
mapStateToProps,
mapDispatchToProps
)(Timeline))Avec pour les action creators :
import { getCollection, fetchCollection } from 'redux-cozy-api'
export const getTimelinePhotos = (state) => getCollection('timeline')
export const fetchTimeline = (skip) => fetchCollection('timeline', 'io.cozy.files', {
fields: ['dir_id', 'name', 'size', 'updated_at', 'metadata'],
selector: {
class: 'image',
trashed: false
},
sort: {
'metadata.datetime': 'desc'
},
skip
})On pourrait améliorer un chouïa ainsi (le fetchMore est fourni par le selector de collections) :
export class Timeline extends Component {
componentWillMount () {
this.props.fetchTimeline()
}
render () {
const { f, photos, fetchTimeline } = this.props
return (
<BoardView
photos{photos.data}
fetchStatus={photos.fetchStatus}
hasMore={photos.hasMore}
onFetchMore={photos.fetchMore}
/>
)
}
}
const mapStateToProps = (state, ownProps) => ({
photos: getTimelinePhotos(state)
})
export const mapDispatchToProps = (dispatch, ownProps) => ({
fetchTimeline: () => dispatch(fetchTimeline())
})
export default translate()(connect(
mapStateToProps,
mapDispatchToProps
)(Timeline))- on est habitué à cette structure là
- fetch et "sélection" du state décorrélés
- besoin d'une instance globale d'un "client" pour gérer plus facilement certaines choses (schemas, indexes...)
const Timeline = ({ photos }) => (
<BoardView
photos{photos.data}
fetchStatus={photos.fetchStatus}
hasMore={photos.hasMore}
onFetchMore={photos.fetchMore}
/>
)
const TimelinePhotos = (ownProps) => ({
photos: {
type: 'io.cozy.files',
selector: {
class: 'image',
trashed: false
},
sort: {
'metadata.datetime': 'desc'
}
}
})
export default cozyConnect(TimelinePhotos)(Timeline)- parait nettement plus clean
- facile d'avoir une instance client, qui en plus reste cachée
- comment gérer les "mutations" ?
- signifie un gros travail sur le HOC car on n'utiliserait plus le
connectdereact-reduxet toutes ses optims
export class Timeline extends Component {
componentWillMount () {
this.props.client.fetchCollection('timeline')
}
updatePhoto = (photo) => {
this.props.client.updateDocument(photo)
}
render () {
const { f, photos } = this.props
return (
<BoardView
photos{photos.data}
fetchStatus={photos.fetchStatus}
hasMore={photos.hasMore}
onFetchMore={photos.fetchMore}
onEdit={this.updatePhoto}
/>
)
}
}
const mapStateToProps = (state, ownProps) => ({
photos: getCollection(state, 'timeline')
})
export default cozyConnect(mapStateToProps)(Timeline)cozyConnect vient injecter t, et surtout client qui détient une ref au store et peut ainsi dispatcher directement des actions. Il wrappe de surcroit le composant avec un connect classique.
- plutôt clean
- mutations faciles à gérer
- le client qui "fuit" dans les composants, mais est-ce si grave ?
- toujours une décorrélation entre le fetch et la sélection du state
Utiliser un middleware redux pour fournir aux action creators génériques de redux-cozy-api une instance de client. Il faut pour cela donner une forme spécifique à ces actions creators :
export const fetchCollection = (collectionName) => ({
type: FETCH_COLLECTION,
promise: (client) => client.fetchCollection(collectionName)
})- le client n'apparait pas dans les composants
- toujours une décorrélation entre le fetch et la sélection du state
On utilise un middleware spécifique de type solution #2 et un HOC spécifique :
class Timeline extends Component {
render () {
const { photos, uploadPhoto } = this.props
return (
<BoardView
photoLists={photoLists}
fetchStatus={photos.fetchStatus}
hasMore={photos.hasMore}
photosContext='timeline'
onFetchMore={photos.fetchMore}
onUpload={uploadPhoto}
/>
)
}
}
export default cozyConnect('photos', () => fetchTimeline(), { uploadPhoto })(Timeline)Avec :
import { fetchCollection, createFile } from '../../lib/redux-cozy-client'
export const fetchTimeline = (skip = 0) => fetchCollection(TIMELINE, FILES_DOCTYPE, {
fields: ['dir_id', 'name', 'size', 'updated_at', 'metadata'],
selector: {
class: 'image',
trashed: false
},
sort: {
'metadata.datetime': 'desc'
}
})
export const uploadPhoto = (photo) => createFile(photo, PHOTO_DIR)On ne peut pas toujours se reposer sur les 5-6 action creators de la lib, certaines actions demanderont toujours un workflow complexe avec le client.
import { fetchCollection, makeActionCreator } from '../../lib/redux-cozy-client'
export const fetchTimeline = (skip = 0) => fetchCollection(TIMELINE, FILES_DOCTYPE, {
fields: ['dir_id', 'name', 'size', 'updated_at', 'metadata'],
selector: {
class: 'image',
trashed: false
},
sort: {
'metadata.datetime': 'desc'
}
})
export const uploadPhoto = (photo, dirName) => makeActionCreator(async client => {
const dir = await client.getOrCreateDirectory(dirName)
return createFile(photo, PHOTO_DIR) // must return a generic action
})
Uh oh!
There was an error while loading. Please reload this page.