Coder Social home page Coder Social logo

redux-json-api's Introduction

Redux JSON API

Make Redux πŸ’œ JSON API

Build Status

This library is intended for use in web applications build on Redux, which consumes data from a JSON API.

Use redux-json-api to have one simple way of storing resource objects in Redux state along with it's CRUD API, which provides easy ways to create, read, update and delete resources.

Please raise any questions as an Issue or submit your contributions as a Pull Request. Remember to review our contributions guidelines.

Table of contents

  1. Set-Up & Configure
  2. API
  3. Selectors
  4. Good reads
  5. Contribute
  6. Contributors

Good reads

  • Working Example App - Quickstart guide to a minimal implementation of Redux JSON API 2
  • Redux - Read about redux and core principles.
  • JSON API - Read about the specifications for JSON API.

Contribute

Got any feedback or suggestions? Review our contribution guidelines.

Contributors

Made with πŸ’œ from Copenhagen and the world. Originally forged in a Founders startup.

redux-json-api's People

Contributors

adz avatar aklkv avatar asiniy avatar berfarah avatar dakota avatar danbradbury avatar dependabot[bot] avatar dpdawson avatar egeriis avatar evolve2k avatar gobadiah avatar ichi avatar istvan-hevele avatar jibran avatar johanmeiring avatar mansona avatar marcw avatar mory1879 avatar narghev avatar nopzen avatar petesta avatar razerm avatar tb avatar tomharvey avatar valikos avatar vexii avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redux-json-api's Issues

When updating state of changed entity related entity is not updated with new relation.

I'm following the API approach for createEntity.

I am updating an entity which is a child of a related entity, to illustrate I'll refer to task and TaskList from the official example as it is adequate currently to illustrate my point.

When createEntity is dispatched it is correctly updating the task to my backend. It is also updating state to include the new task BUT TaskList is not having it's state updated to reflect that it now has this additional task related to it and hence in my UI the new task is not showing as only tasks related to my TaskList show.

Should I be dispatching something further to ensure the TaskList updates to include the new task or should all related entities be updating following the dispatch(createEntity(entity)) as below.

Per: https://github.com/dixieio/redux-json-api/blob/master/docs/apis/createEntity.md

class CreateTask extends Component {
  handleSubmit() {
    const { dispatch } = this.props;
    const entity = {
      type: 'tasks',
      attributes: {
        task: 'New task name'
      },
      relationships: {
        taskList: {
          data: {
            id: '1',
            type: 'taskLists'   <==== Does this also have its relations updated from the dispatch?
          }
        }
      }
    }

    dispatch(createEntity(entity));
  }

Error on deleteEntity

I'm getting a strange error when deleting a resource using deleteEntity.

Uncaught (in promise) TypeError: Cannot read property 'indexOf' of null(..)
            (anonymous function)    @   utils.js:32
            (anonymous function)    @   utils.js:31

from utils.js

    if (res.status >= 200 && res.status < 300) {
      if (jsonContentTypes.some(function (contentType) {
        return res.headers.get('Content-Type').indexOf(contentType) > -1; //breaks here
      })) {
        return res.json();
      }

      return res;
    }

The DELETE request is successful and the server responds with 204 No Content

Since the server is correctly implementing the jsonapi spec for delete (using jsonapi-resources) I'd expect there to be no problem when the response is handled by redux-json-api

We were thinking this could have just been an issue with a missing Content-Type header but from the HTTP/1.1 RFC we see that Content-Type isn't even mandatory when content is available.

Any HTTP/1.1 message containing an entity-body SHOULD include a Content-Type header field defining the media type of that body

From reading up on jsonapi-resources they made a conscious decision to not include Content-Type on 204 No Content which makes sense to me (no content is coming back in the response so why provide a Content-Type for something that doesn't exist)

Is this something that should be fixed on the server side? Or would it make more sense to adjust the above code to handle the res.status === 204 case?

Use promises instead of callbacks for success/error

It would be more appropriate to return a promise from the async action creators, and utilize these to allow a client to respond to succesful and failed API requests.

I believe it would be possible to return a value from the action creator, e.g.:

export const createEntity = (entity) => {
  return (dispatch, getState) => {
    return new Promise((resolve, reject) => {
      apiRequest( ... ).then(json => {
        resolve(json);
      }).catch(error => {
        reject(error);
      });
    });
  };
};

And then allow clients to add resolve/reject callbacks:

dispatch(createEntity( ... )).then(onSuccess).catch(onError);

I think this would be a superior API to the current options object.

Cookie based session credential authentication is not currently supported

I have a redux app that is connected with a Rails backend using the 'react_on_rails' ruby gem.

My redux app was correctly authenticating updates to my backend until I shifted across to redux-json-api. After a lot of hunting around we found that I was doing the call previously with the jquery ajax command and redux-json-api relies upon the newer fetch approach which we found out no longer sends cookies by default and hence the rails backend was not getting sent the session authentication cookie it was expecting.

This turns out to have a quick fix.

Calls to fetch just need to have credentials: 'include', added to them to once again pass credential information across.

Reference: https://developers.google.com/web/updates/2015/03/introduction-to-fetch#sending-credentials-with-a-fetch-request

Sending Credentials with a Fetch Request

Should you want to make a fetch request with credentials such as cookies, you should set the credentials of the request to β€œinclude”.

fetch(url, {  
  credentials: 'include'  
})

I've created a branch that include the changes mentioned and I've got it working with my local app, but my JS skills are limited and so I don't currently have any test coverage.

Here's the change:
evolve2k@b384db6

I'm hoping a more experienced dev could possibly help get this polished up into an acceptable pull request unless you think it's simple enough as it is.

Modify data received from API

I have a filters array that I receive from the API using the read method. With the UI, I can modify those filters and I would like to update the redux store. Is it possible to access the API reducer to add a custom method? what would be the best practice? Thanks

Create ability to catch errors

In both master branch and axios implementation #41 there is no common way how to handle errors, like that:

setAxiosPromiseHandler({
  then: [(result) => { console.log(result) }],
  catch: [(error) => { console.log(error) }],
})

This is extremely helpful feature in things like global authentication. Anywhere when user gets Forbidden, he is redirected to sign in page for example. No need to write same exception handlers anywhere.

What do you think?

Uselessness of redux-json-api

Please correct me if I'm wrong.

Let's say I have a simple structure, like Post & Comment. Read endpoint returning both tasks & comments which are belongs to tasks. So, I have a structure like:

state: {
  api: {
    posts: [array of posts with their ids],
    comments: [array of comments with their ids]
  }, ...
}

I want to get only one element to show it on the page. It requires a js method like find to find a particular post. But after it I need to find a comments for this post, which requires a lot of magic too. Is there any helpers methods or something like that to make structure working elegant?

API_READ fumbles many to many releationships

When a endpoint returns a included data set, the reducer should set the relationship in relationships as an array not and object, with only one relation.

Case: (example call: /api/users?include=comments).

//Backend returns
data: [{
  type: 'users',
  id: 1,
  attributes: {
    name: "Nopzen"
  }
}],
include: [{
  type: 'comment'
  id: 1,
  attributes: {
    text: 'Hello World'
  },
  relationship: {
    user: {
      data: {
        id: 1,
        type: 'users'
      }
    }
}, {
  type: 'comment'
  id: 2,
  attributes: {
    text: 'Goodbye World'
  },
  relationship: {
    user: {
      data: {
        id: 1,
        type: 'users'
      }
    }
}]

After it has been reduced i would come out like this

users: {
 data: [{
    type: 'users',
    id: 1,
    attributes: {
      name: "Nopzen"
    }, 
    relationships: {
      comments: {
        id: 1,
        type: 'comment'
      }
    }
  }]
}

Instead of relationships being and array with both comments in, the reducer turns it to and object with one relation.

Axios

I'd like to suggest the use of axios over fetch. It has quite a few benefits over fetch.

  • Global Auth (Meaning auth would not be a concern of this package, you'd pass through an axios client preconfigured for auth)
  • Interceptors (For an example of why this is useful, I use OAuth for API authentication, so the client deals with hourly access_token refreshes, and needs to handle this transparently, an interceptor allows me to automatically catch 403's and refresh the access_token and re-fire the request with these. I don't have an example Axios implementation, but I do have one for Angular's $http here which is very similar)
  • Generally allows for much more control by the implementation of this package.
  • .then and .catch are properly fired based on the response code, so no more manual status code checking.

If this would be something you're interested in, I'd be happy to fork and add it myself.

Version 1.5 forces redux-thunk to be <2.0

Hey,

in my project I'm using:

"redux-json-api": "^1.4.1",
"redux-thunk": "^2.1.0"

so Travis installed redux-json-api 1.5 but since the peerDependency for "redux-thunk": "^1.0.0" my build will fail because "redux-thunk": "^2.1.0" does not satisfy.

Is there a reason for forcing the dependency to be <2.0?
Maybe the peerDependency can be relaxed?

Use camelCase for entity types

When storing entities, the type should be camelized to adhere to common JS naming conventions.

This could potentially be a setting, whether to use camelCase or snake_case.

Store invalidating flags outside resource object

Currently we are setting the isInvalidating directly on a resource. This means that if a resource is updated through updateEntity is will change two times:

  1. When updateEntity is dispatched (isInvalidating will be set to "UPDATING")
  2. When the PATCH request succeeds/fails (isInvalidating is removed, resource may change)

This may cause an unnecessary re-render, as the resource object has been updated more than necessary.

It's probably not a big issue, but an obvious benefit to harvest, if we move the isInvalidating flag into another place. I think it's valuable to keep, but I don't think a lot of applications use this. However I think the following list specifies a fair set of requirements:

  • Keep references to resources that are invalidating in a central location
  • Keep the invalidating flags easy to find with a resource identifier
  • Store the invalidating flags in a location that doesn't interfere with resource store

Map the 'included' section from the JSON as a prop

In the docs, it shows how to map 'data' as a prop, but what about 'included'?

I've tried like this, but it doesn't show up:

const mapStateToProps = ({ api: { topics = { data: [], included: [] } } }) => ({ topics });

Bug in v1.6

Using the latest version, only 5 records are read from a dataset of 28. Not sure what's the issue but when i revert to v1.5.1, it works fine.

Consider setup of a gitter to help move some of the tricker project issues along with more direct communication?

Would you peeps consider setting up a gitter for the project or are you ever anywhere on IRC this might be easier to resolve over IRC chat, I've made good progress doing so on the other side of the equation chatting on the jsonapi-resouces ruby gem using their gitter.

http://gitter.im/cerebris/jsonapi-resources

Just putting it out there as I've definitley found it slower going with a day by day back and forth on issues that would be better resolved on both sides with more direct communication.

Reducer doesn't work when root-state is Immutable

Internally the module uses ImmutalbleJS for setting the api-states, but the api-reducer cannot be combined with existing reducers when the initialState of the store is Immutable:

For example:

const redux = require('redux');
const Immutable = require('immutable');
const redux_immutable = require('redux-immutable');
const redux_thunk = require('redux-thunk').default;
const redux_json_api = require('redux-json-api');

const api = redux_json_api.reducer;

const reducers = redux_immutable.combineReducers({api});
const initialState = Immutable.Map();
const middlewares = redux.applyMiddleware(redux_thunk);
const store = redux.createStore(reducers, initialState, middlewares );

store.subscribe(() => console.log(store.getState().toJS()) )

store.dispatch(redux_json_api.setEndpointHost('http://ip.jsontest.com/'));
store.dispatch(redux_json_api.setAccessToken('access_token_123123'));

store.dispatch(redux_json_api.readEndpoint('/'))

This code results in:
TypeError: Cannot read property 'endpoint' of undefined: getState().api.endpoint;

The code looks like:

const { host: apiHost, path: apiPath, headers } = getState().api.endpoint;

I think (in case the root-state is Immutable) this should be something like:

const { host: apiHost, path: apiPath, headers } = getState().get('api').endpoint;

Update entity fails if not performed other operation to the endpoint before

I'm trying to call the function updateEntity and I'm getting this error:
Uncaught TypeError: Cannot read property 'update' of undefined
happening in this line:

screen shot 2016-12-06 at 15 24 15

I found out that since I'm calling updateEntity on this endpoint api before calling any other operation such as readEndpoint or createEntity, the endpoint api name (which is also the entities type) is not a property in the state of redux-json-api, and that's why I am receiving the undefined error.

For example, if I'm calling readEndpoint before calling updateEntity, everything works fine, since the endpoint api name (entities type) is added as a property to the state.

In my case, it's unnecessary to call readEndpointfirst, since I already have all the necessary data for updating the entity.

I would like to be able to call updateEntity without assuming other operations were called before.

Helper component to handle CRUD API operations

How can I make a Helpers component to handle CRUD API methods and other utilities? I could use a regular component but I don’t need the render method

I need to access this.props.dispatch so using module.exports doesn’t work well for that, because when I pass this.props.dispatch as an argument to readAPI, I get dispatch is not a function(…):

Helpers.jsx:

import { readEndpoint, deleteEntity, createEntity, setEndpointHost, setEndpointPath, setAccessToken } from 'redux-json-api';
import { API_URL, API_PATH } from '../../constants/constants';

module.exports = {
    
   configAPI: function(token, dispatch) {
		dispatch(setEndpointHost(API_URL));
		dispatch(setEndpointPath(API_PATH));
		dispatch(setAccessToken(token));
	},
	
	readAPI: function(token, endpoint, dispatch, callback) {
		this.configAPI(token, dispatch);
		dispatch(readEndpoint(endpoint)).then(function(data) {
			callback(data);
		}.bind(this));	
	},
}

This is how I would call it:

Helpers.readAPI('my_API_token', 'whatever', this.props.dispatch, function(data) {
     // Do whatever
});

Problem populating datastore

I'm having trouble getting redux-json-api to populate my data store. I've created an example project here: https://github.com/wgAtTS/react-redux-json-api

When I call dispatch() the action fires, and I can see JSON being returned from the server. However, the JSON never makes it into the redux store. Here's a screenshot of what I'm talking about:

screen shot 2016-04-26 at 11 28 48

api.tasks should not be null. You can ignore the additional "tasks" at the root level - I was using that for debugging (I'm new to React/Redux).

Can you provide any insight? Thanks!

Module not found: Error

Hey,

while trying to get started with redux-json-api me and my coworker run into that error, while trying to start our application.

ERROR in ./~/redux-json-api/lib/jsonapi.js
Module not found: Error: Cannot resolve module 'babel-runtime/helpers/defineProperty' in /Users/juliakruger/Repos/backoffice-react/node_modules/redux-json-api/lib
 @ ./~/redux-json-api/lib/jsonapi.js 3:23-70

ERROR in ./~/redux-json-api/lib/jsonapi.js
Module not found: Error: Cannot resolve module 'babel-runtime/helpers/extends' in /Users/juliakruger/Repos/backoffice-react/node_modules/redux-json-api/lib
 @ ./~/redux-json-api/lib/jsonapi.js 7:16-56

ERROR in ./~/redux-json-api/lib/jsonapi.js
Module not found: Error: Cannot resolve module 'babel-runtime/core-js/json/stringify' in /Users/juliakruger/Repos/backoffice-react/node_modules/redux-json-api/lib
 @ ./~/redux-json-api/lib/jsonapi.js 11:17-64

ERROR in ./~/redux-json-api/lib/jsonapi.js
Module not found: Error: Cannot resolve module 'babel-runtime/core-js/promise' in /Users/juliakruger/Repos/backoffice-react/node_modules/redux-json-api/lib
 @ ./~/redux-json-api/lib/jsonapi.js 15:15-55

ERROR in ./~/redux-json-api/lib/utils.js
Module not found: Error: Cannot resolve module 'babel-runtime/helpers/extends' in /Users/juliakruger/Repos/backoffice-react/node_modules/redux-json-api/lib
 @ ./~/redux-json-api/lib/utils.js 3:16-56
webpack: bundle is now VALID.

I tried to remove my node_modules, run npm cache cleanand npm install but the errors was still there.
we could reslove this however, by adding your dependecies to our own:

npm install --save-dev babel-preset-stage-0 babel-plugin-transform-runtime babel-plugin-add-module-exports
npm install --save babel-runtime

do you know what is happening there?

Update action returns list out of order

I was wondering if there is a way to specify the ordering on an array or have the resulting array not change its ordering. Let's say you're referring to the users of a company, on updateEntity. For example, if all users are already listed in order by id then when you call updateEntity lets say to change the name of the first user in the array, the resulting array will return out of order.

// The structure and ordering of data before the call
[
  {
    id: 1,
    name: "John"
  },
  {
    id: 2,
    name: "Emily"
  },
  {
    id: 3,
    name: "Jordan"
  }
]

// After call to updateEntity

[
  {
    id: 2,
    name: "Emily"
  },
  {
    id: 3,
    name: "Jordan"
  },
  {
    id: 1,
    name: "John Doe"
  }
]

Add missing support for a complete URL passed as endpoint.

When passing a complete URL as the endpoint, in this case a pagination.

"http://my.app/api/v1/companies/1/timelineItems/?page%5Bcache%5D=1xfupzj63rtx&page%5Bpage%5D=2"

Redux json api should recon. that this is a fully specified URL and just query the URL given from the backend, that it expects, instead of applying it as a endpoint. current situration happens below:

"http://my.app/api/v1/http://my.app/api/v1/companies/1/timelineItems/?page%5Bcache%5D=1xfupzj63rtx&page%5Bpage%5D=2"

Clear state

Hey Guys,

Whenever I make a request to readEndpoint it updates my state as I expected, but there are times when I really don't want to keep storing all this info in state and adding to it every time. One example of this in my case is a search functionality, every time I search I increase the amount of info in the state and I really want to simply replace what was there with the response from the last read.

It would be nice to have if the readEndpoint action creator took some options one of which been to replace or concat the results like:

readEndpoint("/search/foo", { clear: true })

This is just an example and that might be quite an ugly api and you can think of a better approach. Alternatively, is there a way to extend your reducer so I can do this manually?

Chris

Remove uploadFile method

The uploadFile has nothing to do with JSON API. It is legacy from previous usage and should be removed.

CORS support

In my project endpoint hosts on another domain. window.fetch doesn't allow to make requests to another domain without special mode param.

Pass custom options to fetch

There is currently no way (that I can see) to pass custom options to the fetch function in utils.js. I need to be able to pass credentials: 'include' in the options hash for basic auth to work.

It'd be nice to set this as a global config option like host and path.

Bug in v1.6.1: redux adding up new values into resource on each readEndpoint call

This is the sequence to replicate the issue:

Step 1. Load endpointA with queryString Q = 1:

  • Resource R receives 2 items of type T)
  • Redux displays 2 items in resource R

Step 2. Load endpointA with queryString Q = 2:

  • Resource R receives 1 item of type T)
  • Redux displays 3 items in resource R (it should display just one...)

Step 3. Load endpointA with queryString Q = 1:

  • Resource R receives 2 items of type T)
  • Redux displays 5 items in resource R (it should display just two...)

Step 1.

screen shot 2016-11-22 at 14 26 08

Step 2.

screen shot 2016-11-22 at 14 26 45

Step 3.

screen shot 2016-11-22 at 14 32 16

Change API names to be spec-compatible

Currently we use the term "entity" which is not in line with JSON API documentation, which uses the term "resource". This should be updated so there are no confusion around the taxonomy.

Deprecate old methods

As per suggestion in #84, to prepare users of v1.x for upgrade to v2.0, old API method names will now be deprecated and note that they will be removed in v2.0.

State not updateding and getting Response object with body ReadableByteStream

Hey,

Firstly this is a nice project, Im new to react/redux and also the jsonapi spec so Im sort of fumbling my way through. That said I have an issue that I will fully accept could be on the part of my lack of understanding but here goes.

When I setup the api host/path and dispatch an action to read an entity I did expect that the state would be updated. However what I am seeing is that the state remains unaltered. I also hooked into you onsuccess callback but instead of the serialized json body I have a Response object. Here are the steps:

store.dispatch(setEndpointHost("http://localhost:4000"));
store.dispatch(setEndpointPath("/api"));
store.dispatch(readEndpoint("venue", {
        onSuccess: (result) => console.log(result),
        onError: (result) => console.error(result)
    }));

Resulting in:

Response {type: "basic", url: "http://localhost:4000/api/venue", status: 200, ok: true, statusText: "OK", body: ReadableByteStream...}

When I look at your code: https://github.com/dixieio/redux-json-api/blob/master/src/jsonapi.js#L243 I see that you expect the payload dispatched to have a data property which I haven't got. Is there some middleware magic at work here to convert this to what you need, and if so why do I still not see the state changing?

Cheer, Chris

Examples in README

Hi, thanks for this!

I'm having trouble with the Usage instructions. I've created a store with the included reducer and the initial empty state is loaded (in this case into react). I have not been able to setup the endpoint or use it beyond this. Are there any examples? Even just expand the Usage section in the read me with where and how to use the setup and initial read actions/methods.

I have one more basic question --- JSON-API is not a data structure but describes a data structure. I still have to manually convert JSON-API into props objects easily usable in react components? Any tips on where/how it's best to do that?

Update and improve README

I am trying to use your library, but it is very hard. It seems that README is outdated. Could you please update it and also add atleast one full example, where you get data from server in your state? It would be very helpful!

readEndpoint in a container with mapDispatchToProps

Hi,

I have a container, app.jsx, which already has mapStateToProps and mapDispatchToProps for a custom reducer I built called mainReducer. If I use the method explain in the docs to read an API endpoint, (this.props.dispatch(readEndpoint(...))), then I would get this error: Uncaught TypeError: this.props.dispatch is not a function. I guess because I'm using mapDispatchToProps for my custom reducer and that conflicts with the library.

The only way to make it work with readEndpoint was to add readEndpoint, setEndpointHost, setEndpointPath, setAccessToken to mapDispatchToProps, which changes the way I call these methods (I no longer use .dispatch()):

componentDidMount() {
        this.props.setEndpointHost(API_URL);
        this.props.setEndpointPath(API_PATH);
        this.props.readEndpoint('start');
    }
const mapStateToProps = ({ mainReducer: { isLoading, isOpened, isDesktop }, api: { start = { data: [] }, header = { data: [] } } }) => ({ isLoading, isOpened, isDesktop, start, header });

const mapDispatchToProps = {
    setLoading,
    setOpened,
    changeViewport,
    readEndpoint,
    setEndpointHost,
    setEndpointPath,
    setAccessToken
};

export default connect(mapStateToProps, mapDispatchToProps)(App);

So far, so good, the problem comes when in a child container navigation.jsx, I need to make another readEndpoint. In this case, because I passed down all the props from app.jsx to the children, then when I try to make the calls, I always get an infinite loop with the following errors:

warning.js?0260:36 Warning: performUpdateIfNecessary: Unexpected batch number (current 1638, pending 1637)printWarning @ warning.js?0260:36warning @ warning.js?0260:60performUpdateIfNecessary @ ReactReconciler.js?6bfa:150runBatchedUpdates @ ReactUpdates.js?ce09:151perform @ Transaction.js?6dff:138perform @ Transaction.js?6dff:138perform @ ReactUpdates.js?ce09:90flushBatchedUpdates @ ReactUpdates.js?ce09:173closeAll @ Transaction.js?6dff:204perform @ Transaction.js?6dff:151batchedUpdates @ ReactDefaultBatchingStrategy.js?ef70:63enqueueUpdate @ ReactUpdates.js?ce09:201enqueueUpdate @ ReactUpdateQueue.js?fd2c:25enqueueSetState @ ReactUpdateQueue.js?fd2c:210ReactComponent.setState @ ReactComponent.js?702a:64handleChange @ connect.js?243b:301dispatch @ createStore.js?fe4c:186dispatch @ VM1325:1(anonymous function) @ index.js?f248:14dispatch @ applyMiddleware.js?ee15:45(anonymous function) @ jsonapi.js?64db:204 warning.js?0260:36 Warning: performUpdateIfNecessary: Unexpected batch number (current 1640, pending 1637)

I think this is due to this.props.readEndpoint being defined in app.jsx and passed down to navigation.jsx, which then conflicts with the new readEndpoint. I can't avoid passing down the props because I'm using {React.cloneElement(this.props.children, this.props)} in app.jsx to make the API token available to all the components in the app.

I've also tried to use the classic this.props.dispatch(...) in navigation.jsx but the result is the same. It seems that once I add the API methods into mapDispatchToProps, the whole thing breaks.

Any suggestion regarding how could this approach be architected? Many thanks

Mix api reducer with another custom reducer

Hi,

So far I had no issues with mapping to props the types received from my API reducer, but now I find myself in the need of combining the map to props from the API and from another reducer mainReducer I'm using in the app.

How can I combine the two reducers when mapping to props? This is how I'm trying to do it:

const mapStateToProps = ({
    api: {
        questions = {
            data: []
        },
        filters = {
            data: []
        },
        tables = {
            data: []
        },
        columns = {
            data: []
        },
        answers = {
            data: []
        }
    },
    mainReducer: {
        currentFilters = {
            data: []
        }
    }
}) => ({ questions, filters, tables, columns, answers }, { currentFilters });

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ setFilters: setFilters }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Report);

This approach is giving me an error that I wasn't getting when I only had the API stuff:

Uncaught (in promise) TypeError: this.props.dispatch

Redux-saga support

In our project I have been working with the redux-saga.

Is there a version of the work of the redux-json-api with the redux-saga instead redux-thunk?

Add changelog for v1.x -> v2.0

  • Change from fetch to Axios, requires changes in client configuration #41
  • New response object in fulfillment handler #21
  • uploadFile removed #49
  • onSuccess/onError removed #50
  • Note how to pass custom headers in request (e.g. access-control headers)

Etags

Hi guys,
first of all thanks for the awesome work!

I'm quite new to React - Redux and your awesome library

I have a question regarding ETags.
Does your library support ETags? and if, how?

Conventionally I tried to pass a 2nd argument into readEndpoint like
readEndpoint(route, {'If-None-Match': '123'})

But apparently that doesn't work. :/

Cheers

How to use my own fork of this repo on github

Hey I've forked the repo and been playing around with my own changes but I keep needing to manually copy the changes into the node_modules directory of my project and Im also having random dependancy issues depending on what Im trying to do.

I've asked generically on SO, and googled a lot but it seems it's an it depends type answer.

I figured you folks are regularly working on this code and have your own private branches you're possibly developing.

What do I need to do to the project so that I can use my own fork, it seems I need to compile it so that dependancies are included and ensure that's available on the github repo from my understanding.

(Specifically right now Im monkey patching the code to test my issue of what if I forced the url to include a caterpillar/dasherized version of the entity.type in the path, as per this issue (#62) but Im also wanting to test my own code changes with this repo generally).

Just to clarify I know how to refer to my own repo from package.json like so,
"redux-json-api": "https://github.com/evolve2k/redux-json-api.git#dasherized",
but Im needing to know how to prepare the repo so it just works when referred to as above.

Thx

Ajax call is fine but the redux store is not getting the data

Hi,

First of all many thanks for your work. This library looks promising (if I can make it work). I'm just trying to read a simple JSON stub and get it into the redux store. The first part (loading the data) works fine. I can see it with a console.log in the promise:

componentDidMount() {
        this.props.dispatch(setEndpointHost(''));
        this.props.dispatch(setEndpointPath(''));
        this.props.dispatch(readEndpoint('data/navigation.json')).then(function(data) {
            console.log(data);
        });
    }

What it doesn't work for me is having the data in the redux store. I just get an empty container for the navigation key.

This is my store.jsx:

import { createStore, applyMiddleware } from 'redux';
import { syncHistoryWithStore } from 'react-router-redux';
import { browserHistory } from 'react-router';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

const store = createStore(rootReducer, applyMiddleware(thunk));

export const history = syncHistoryWithStore(browserHistory, store);

export default store;

My container:

import React, { Component, PropTypes } from 'react';
import Category from '../components/lib/category/category';
import sidebarStyles from '../styles/partials/sidebar.scss';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { readEndpoint, setEndpointHost, setEndpointPath } from 'redux-json-api';

const defaultProps = {

};

const propTypes = {

};

class Sidebar extends Component {

    componentDidMount() {
        this.props.dispatch(setEndpointHost(''));
        this.props.dispatch(setEndpointPath(''));
        this.props.dispatch(readEndpoint('data/navigation.json')).then(function(data) {
            console.log(data);
        });
    }

    render() {
        return ()
    }
}

const mapStateToProps = ({ api: { navigation = { data: [] } } }) => ({ navigation });

export default connect(mapStateToProps)(Sidebar);

The combined reducers:

import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import { reducer as api } from 'redux-json-api';
import mainReducer from './mainReducer';

const rootReducer = combineReducers({mainReducer: mainReducer, api: api, routing: routerReducer});

export default rootReducer;

The JSON file:


{
    "data": {
        "type": "answers",
        "id": "1",
        "links": {
            "self": "/answers/1"
        },
        "relationships": {
            "jokes": {
                "links": {
                    "self": "/answers/1/relationships/jokes",
                    "related": "/answers/1/jokes"
                },
                "data": [
                    {
                        "type": "jokes",
                        "id": "1"
                    }
                ]
            },
            "weather": {
                "links": {
                    "self": "/answers/1/relationships/weather",
                    "related": "/answers/1/weather"
                },
                "data": [
                    {
                        "type": "weather",
                        "id": "1"
                    }
                ]
            }
        }
    },
    "included": [
        {
            "type": "jokes",
            "id": "1",
            "attributes": {
                "joke": "Did you hear about the guy whose whole left side was cut off? He's all right now."
            },
            "links": {
                "self": "/jokes/1"
            },
            "relationships": {
                "actions": {
                    "links": {
                        "self": "/jokes/1/relationships/actions",
                        "related": "/jokes/1/actions"
                    },
                    "data": [
                        {
                            "type": "actions",
                            "id": "ask_me_another"
                        },
                        {
                            "type": "actions",
                            "id": "noop"
                        }
                    ]
                }
            }
        },
        {
            "type": "actions",
            "id": "ask_me_another",
            "attributes": {
                "type": "jokes",
                "label": "ask-me-another",
                "verb": "get"
            },
            "links": {
                "self": "/actions/ask_me_another"
            }
        },
        {
            "type": "actions",
            "id": "noop",
            "attributes": {
                "type": "jokes",
                "label": "not-funny",
                "verb": "get"
            },
            "links": {
                "self": "/actions/noop"
            }
        },
        {
            "type": "weather",
            "id": "1",
            "attributes": {
                "city": "London",
                "summary": "Partly Cloudy",
                "temperature": 21.09
            },
            "links": {
                "self": "/weather/1"
            },
            "relationships": {
                "actions": {
                    "links": {
                        "self": "/weather/1/relationships/actions",
                        "related": "/weather/1/actions"
                    },
                    "data": []
                }
            }
        }
    ]
}

And this is what I get:

screen shot 2016-09-22 at 13 37 28

screen shot 2016-09-22 at 13 38 32

screen shot 2016-09-22 at 13 52 53

Consider documenting return signature of readEndpoint

Hello,

I've started playing around with redux-json-api, migrating from a JSON API JS client my team wrote ourselves. So far it's wonderfully easy to use (well, after I read the docs in progress in #31 :) ), but I'm stuck on one common case that I don't see a natural pattern for. If you perform an endpoint read that returns multiple results (as in the case for e.g. a search query), state.api is populated with all of them correctly -- but how do you know which entries correspond to the API read you just issued, as opposed to another API read?

I think the way around this looks something like this (below is a simplified example):

  • an additional reducer:
const queryStore = (state={}, action) => {
  if(action.type == 'API_READ') {
    return Object.assign({}, state, {[action.payload.endpoint]: action.payload.data.map(el => el.id)});
  }
  else {
    return state;
  }
};
  • an action dispatch that looks like this:
this.props.dispatch(readEndpoint('/api/path?search=' + state.foo));
  • and a mapStateToProps that looks like this:
function mapStateToProps(state) {
  return {
    search_results: (state.queryStore['/api/MyObject?search=' + state.foo]).map(id => {
      return _.find(state.api.MyObject.data, {id: id});
    });
}

... but the additional reducer and the additional queryStore state entry to keep track of outstanding queries makes it seem like I'm doing something wrong, since that's all stuff I would assume the library would track. This is also a very naive implementation, so e.g. you need to manually remove entries from state.queryStore if you want to re-issue the find.

Am I missing something, or is this how the library is meant to be used?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.