项目作者: fakundo

项目描述 :
Provides an extra layer of 'getters' between your React components and the Redux store
高级语言: JavaScript
项目地址: git://github.com/fakundo/react-redux-getters.git
创建时间: 2017-11-05T23:33:44Z
项目社区:https://github.com/fakundo/react-redux-getters

开源协议:MIT License

下载


react-redux-getters

npm

Provides an extra layer of ‘getters’ between your React components and the Redux store.
The getter returns the data from the store, if it’s there, otherwise it returns a stub and invokes the fetch action.
So the store is filled automatically.

Installation

  1. yarn add react-redux-getters

Usage

Create getter

  1. import { createGetter } from 'react-redux-getters'
  2. import { updateSubjects, fetchSubjects } from 'actions/subjects'
  3. export const getSubjects = createGetter({
  4. stateSelector: (state) => state.subjects,
  5. asyncFetcher: () => fetchSubjects(),
  6. stateUpdater: (data, dispatch) => dispatch(updateSubjects(data)),
  7. })

Configure store

  1. import { createStore, applyMiddleware } from 'redux'
  2. import { gettersMiddleware } from 'react-redux-getters'
  3. const store = createStore(
  4. reducers,
  5. applyMiddleware(gettersMiddleware, ...),
  6. )

Component

  1. import React, { Component } from 'react'
  2. import PropTypes from 'prop-types'
  3. import { connectGetters } from 'react-redux-getters'
  4. import { getSubjects } from 'selectors/subjects'
  5. class Subjects extends Component {
  6. static propTypes = {
  7. subjectsGetter: PropTypes.object.isRequired
  8. }
  9. render() {
  10. const { subjectsGetter } = this.props
  11. const { isSucceded, isPending, isFailure, error, data } = subjectsGetter
  12. if (isPending) {
  13. return (
  14. <LoadingRenderer ></LoadingRenderer>
  15. )
  16. }
  17. if (isFailure) {
  18. return (
  19. <ErrorRenderer error={error} ></ErrorRenderer>
  20. )
  21. }
  22. return (
  23. <DataRenderer data={data} ></DataRenderer>
  24. )
  25. }
  26. }
  27. const mapGettersToProps = (state) => ({
  28. subjectsGetter: getSubjects(state),
  29. })
  30. export default connectGetters(mapGettersToProps)(Subjects)

Done!

Your React component will be rerendered when the getter fetches the data and stores it in the Redux store.

Usage with reselect

Create selector with getter

  1. import { createSelector } from 'reselect'
  2. import { createGetter, composeGetters } from 'react-redux-getters'
  3. import { getSubjects } from 'selectors/subjects'
  4. import { getTeachers } from 'selectors/teachers'
  5. export const getHumanitarianSubjects = createSelector(
  6. getSubjects,
  7. (subjectsGetter) => composeGetters(
  8. subjectsGetter,
  9. (subjects) => filterHumanitarianSubjects(subjects)
  10. )
  11. )

Component (usage is the same as with a regular getter)

  1. import React, { Component } from 'react'
  2. import PropTypes from 'prop-types'
  3. import { connectGetters } from 'react-redux-getters'
  4. import { getHumanitarianSubjects } from 'selectors/subjects'
  5. class HumanitarianSubjects extends Component {
  6. static propTypes = {
  7. humanitarianSubjectsGetter: PropTypes.object.isRequired
  8. }
  9. render() {
  10. const { humanitarianSubjectsGetter } = this.props
  11. const { isSucceded, isPending, isFailure, error, data } = humanitarianSubjectsGetter
  12. ...
  13. }
  14. }
  15. const mapGettersToProps = (state) => ({
  16. humanitarianSubjectsGetter: getHumanitarianSubjects(state),
  17. })
  18. export default connectGetters(mapGettersToProps)(HumanitarianSubjects)

More examples

Composing getters

  1. import { createSelector } from 'reselect'
  2. import { createGetter, composeGetters } from 'react-redux-getters'
  3. import { getSubjects } from 'selectors/subjects'
  4. import { getTeachers } from 'selectors/teachers'
  5. export const getSubjectsAndTeachers = createSelector(
  6. getSubjects,
  7. getTeachers,
  8. (subjectsGetter, teachersGetter) => composeGetters(
  9. subjectsGetter,
  10. teachersGetter,
  11. (subjects, teachers) => ({ subjects, teachers })
  12. )
  13. )

Using props

  1. // Getter
  2. import { createGetter } from 'react-redux-getters'
  3. import { fetchTeacher, updateTeacher } from 'actions/teachers'
  4. export const getTeacher = createGetter({
  5. stateSelector: (state, props) => state.teachers[props.teacherId],
  6. asyncFetcher: (dispatch, state, props) => fetchTeacher(props.teacherId),
  7. stateUpdater: (data, dispatch, state, props) => dispatch(updateTeacher(props.teacherId, data))
  8. })
  9. // Component
  10. import React, { Component } from 'react'
  11. import PropTypes from 'prop-types'
  12. import { connectGetters } from 'react-redux-getters'
  13. import { getTeacher } from 'selectors/teachers'
  14. class Teacher extends Component {
  15. ...
  16. }
  17. const mapGettersToProps = (state, props) => ({
  18. teacherGetter: getTeacher(state, { teacherId: props.teacherId }),
  19. })
  20. export default connectGetters(mapGettersToProps)(Teacher)
  21. // Using component
  22. <Teacher teacherId={1} ></Teacher>

Composing getters without reselect

  1. import { composeGetters } from 'react-redux-getters'
  2. import { getSubjects } from 'actions/subjects'
  3. export const getSubject = (state, props) => composeGetters(
  4. getSubjects(state),
  5. (subjects) => findSubjectById(subjects, props.subjectId)
  6. )

API

  1. import { createGetter, composeGetters } from 'react-redux-getters'
  2. createGetter({
  3. stateSelector: (state, props) => dataFromState, // Required func – should return data from store state
  4. asyncFetcher: async (dispatch, state, props) => fetchedData, // Required async func – should return fetched data (Promise)
  5. stateUpdater: (data, dispatch, state, props) => {}, // Required func - should dispatch store update
  6. shouldFetch: (dataFromState, state, props) => isNil(dataFromState) // Optional func – condition that fetching is needed
  7. })
  8. composeGetters(
  9. ...getters,
  10. composeData: (...gettersData) => newComposedData // Func – creates composed data from incoming getters data
  11. )

License

MIT