Giter Club home page Giter Club logo

redux-bees's People

Contributors

ifiokjr avatar lorezz avatar mahmoudalyudeen avatar stefanoverna avatar theguth avatar vlanemcev avatar zofiag 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-bees's Issues

request timeout?

My server isn't responding to redux-bees requests currently, so the request in the network tab of chrome dev tools just says pending forever -- meanwhile, the component renders over and over again -- I eventually get a maximum call stack reached error.

Is there anyway to specify how long to wait for a request to resolve before giving up?

Non-static API Key?

In the example app, the API key is static. What if the API depends on a particular user having his own API key?

In the "Customize headers" section fo the README, I think this example assumes the store is instantiated and has the API key already. But what if you must fetch it first? There's no action to set the API key on Bees.

Does anyone have an example of a non-static API key that would work outside a single file with a self-contained app?

Add a meta field

Hi, @stefanoverna !
In the json-api specification, it is possible to create a meta field in a resource object and pass non-standard meta-information there.
http://jsonapi.org/format/#document-top-level
Sometimes this is useful and you need to keep this information in the state of our application.
For my application, this is exactly what I need, but I was faced with the fact that the library does not add meta information anywhere.

I analyzed the code and thought about how and where to add this meta-object.
I think it's best to do this in reducers/entities.js in line number 37, you can just add the code:

if(meta) { newState = immutable.set( newState, 'meta', meta ); }

escape query HOC with conditionals

Currently I want to do something like this:

@query('categories', ingester.getCategories, (perform, {params}) => {
  if (!params.categoryId) {
    return perform()
  }
})

But because query always expects a function to be returned I have to do this:

@query('categories', ingester.getCategories, (perform, {params}) => {
  if (!params.categoryId) {
    return perform()
  }
  return () => {}
})

Adding custom header to single request

Hi,
Is there an options to add a custom header to a single endpoint only. For example my login expects a POST request with content-type application/x-www-form-urlencoded but all other posts are expecting json

Thanks

Pagination

Hi, looking to use this on a project. Just had a quick question about doing pagination with the query HoC. Would you have any examples of doing that? query wouldn't provide enough on its own to support displaying a component with paging correct? The props it would provide would just be for the requests it performed. I was thinking you would have some kind of UI state in your store that controls the current page, query and perform would hook into that to issue calls and I guess I'd need a custom piece in my mapStateToProps to pull in all the data (existing calls that happened + the new page)?

Or would it be better to not use the HoC in those contexts? Just dispatch the events myself? Wondering how you guys handle pagination in your app that uses this library. Any guidance would be appreciated!

[Feedback/Feature Request]: Allow using state selectors without specifying the args

Hi!

I recently started using this library and so far I've been very impressed. I have run into a bit of an issue though that I think either I'm doing something I'm not supposed to, or this is a case where it could be made easier to use.

Per the documentation, if I perform a fetch such as dispatch(api.getPosts({ is_active: true })), I can retrieve the results in my mapStateToProps function by writing getRequestInfo(state, api.getPosts, [{ is_active: true }]).

That works fine, however, I also want to put the search criteria into my query string so the search persists if the page gets refreshed. After a round trip through the query string, the parameter becomes { is_active: "true" } and it fails to match the request that's already in the redux store because "true" !== true. I could transform any non-string query string parameters, but that sounds like a nightmare to have to maintain.

I'd like to see an option to fetch a request using a given name dispatch(api.getPosts({ is_active: true }, { requestId: "search" })) and then retrieve it using the name instead of the args getRequestInfo(state, api.getPosts, { requestId: "search" }). Does that sound feasible?

As a hack, I was able to approximate this behavior by adding a toJSON override to my query object: { is_active: "true", toJSON() { return "search" } } and it worked, I could retrieve it with getRequestInfo(state, api.getPosts, ["search"]).

[Question] Redux Dependency

This looks great! The declarative data fetching reminds me of the Preact ecosystem's wiretie, and I've been passively hoping for a React equivalent.

Quick question: if I just want to use the Query HOC as a general purpose declarative fetch using local component state, is that possible without integrating with a Redux store? Wondering if implementation is as coupled to Redux as the name implies ๐Ÿ˜„

Add ability to add endpoints to the built API

If you use redux-bees in a chunked application, the logic for many other pages can be chunked up into files that can be loaded later with Webpack JSONP but the object for API calls will be full of endpoints that won't be used - making the main chunk file larger.

So you should add the ability to call this function which would generate a new function, for example, API.getDifferentPosts() dynamically.

API.addEndpoints({
    getDifferentPosts: { method: get, path: '/path/to/different/apis' }
});

Cache invalidation ignored?

Nice library, everything works as expected, except for one thing I'm confused about.

Calling invalidateRequests successfully sets invalid=true in my store. However the only place in the redux-bees code where this is checked is in the hasRequestStarted selector.

I would have thought this would cause other selectors to ignore that item in the store, but that doesn't seem to be the case. Invalidating an API call effectively seems to do nothing. What is the intended usage?

Query using already fetched data from redux store

I my our setup we want the query HOC to fetch the data, save it in the redux store (which it obviously does), but reuse that data, when its component is mounted for a second time, and avoid that extra http call.
What would be a good way of achieving this?

Uncaught (in Promise)

Hey!

Thanks for bees!
When I receive a 404 or any other error response the console show an uncaught error.

Uncaught (in promise) Object

Everything still works, but I'm wondering why this error appears.

Using redux-bees with before middleware or redux-saga

I've reached a number of dead ends implementing redux-bees and I'm struggling to find a way forward due to two core issues. First, let me explain my requirements:

  1. I want to consume a JSON-API
  2. My API uses OAuth 2 for authentication
  3. I want all the good things from redux-bees like caching, writing data to the store etc.

Unfortunately, it seems thus far that there are a number of inherent issues that prevent me from having this. Most notably being that I may need to refresh a token before the API is requested. To avoid this happening more than once for concurrent requests I've implemented redux-saga to solve

@query() doesn't dispatch any action before the fetch is made

If it did I could:

  1. Watch for the action in redux-saga and defer it until I had a valid token.
  2. Watch for the action in a middleware and stop it if the token needed refreshing.

If I don't use @query I lose all of the good aspects of redux-bees

If I instead:

  1. Dispatch an action like GET_AUTHENTICATED_USER from my component
  2. Watch for that action in redux-saga
  3. Ensure I have a valid token
  4. Call the API directly api.getAuthenticatedUser()

The request works fine, I get back the data but no further dispatches are made that put the data into the store.

I'm at a little bit of a loss over how to proceed without dropping this library. Perhaps I'm missing something. I'd very much appreciate it if @stefanoverna could provide some further insights into the issues I've been facing.

'before' middleware

Besides 'after' middleware(s), a 'before' middleware would probably also be a good idea.
I recently ran into an issue where I had to refresh a token if it was past a certain date.
I ended up wrapping all my api calls & query decorators with a check that would do the refresh, but it'd of course be much better if this could be configured globally from bees itself.

I think it'd look something like this:

  before(...args) {
    return new Promise(resolve => setTimeout(() => resolve(...args);
  },

Retrieving included data for multiple objects

Hi, I'm using redux-bees for my project to interface with my JsonApi backend.

I'm having problems accessing data that's included with a response from my backend using the getRelationship() method.

The example included in the readme covers how to use getRelationship() and connect() to retrieve included data with a single object, but the response I'm working with has multiple objects that each map to some included data.

This is the response I get from the backend, I want to access the cities included with it.

{
    "data": [
        {
            "id": "1",
            "type": "countries",
            "attributes": {
                "title-en": "Kuwait",
                "title-ar": "ุงู„ูƒูˆูŠุช"
            },
            "relationships": {
                "cities": {
                    "data": []
                }
            }
        },
        {
            "id": "2",
            "type": "countries",
            "attributes": {
                "title-en": "Egypt",
                "title-ar": "ู…ุตุฑ"
            },
            "relationships": {
                "cities": {
                    "data": [
                        {
                            "id": "7",
                            "type": "cities"
                        },
                        {
                            "id": "8",
                            "type": "cities"
                        }
                    ]
                }
            }
        }
    ],
    "included": [
        {
            "id": "7",
            "type": "cities",
            "attributes": {
                "slug": "cairo",
                "title-en": "Cairo",
                "title-ar": "ุงู„ู‚ุงู‡ุฑุฉ"
            },
            "relationships": {
                "areas": {
                    "data": []
                }
            }
        },
        {
            "id": "8",
            "type": "cities",
            "attributes": {
                "slug": "alexandria",
                "title-en": "Alexandria",
                "title-ar": "ุงู„ุฃุณูƒู†ุฏุฑูŠุฉ"
            },
            "relationships": {
                "areas": {
                    "data": []
                }
            }
        }
    ]
}

Headers as a function

As with baseUrl it would be nice if the headers configuration could also be dynamic. The headers may change as when a user logs in.

TypeScript Support

I'm now using this library within a TypeScript project. Would it be fine to submit a PR with typings for full TypeScript support?

API call cannot be performed. The following params were not specified: index

I have a problem for my routes, I try to call a route with 2 params in it but a got the following message : API call cannot be performed. The following params were not specified: index

Here the declaration of my route
endPoind: { method: destroy, path: '/api/model/:id/subModel/:index' }

And here how I call it
Api.endPoind({ id: 12, index: 0 })

If someone have any idea to resolve it, or if do something bad

API call cannot be performed. The following params were not specified: id

Hi, I'm using redux-saga for async actions. And faced with this issue. I'm getting the error (proxyConsole.js:56 The "putJob" API call cannot be performed. The following params were not specified: id) when trying to make a put request.

But I don't have this error for get method in exact same code.

api.js

...
putJob: { method: put, path: "/jobs/:id" },
...

putJobSaga.js

...
const newJob = yield call(API.putJob, { id: id });
...

Server side rendering

In a server side rendering set up, you'd preferably not render any components until all of them have their data ready.
Has there been put any thought into this yet?
Specifically in combination with the query HOC?

Here's how I think it could look:

The query.js Wrapper class exposes a static function which accepts a redux dispatch function as first argument. It will return a promise that resolves once data is loaded, and dispatches all data to the passed redux function along the way.
The server (with the help of react-router or something similar) then checks which components match the route path and calls all of the static functions if they're available.
Then, if all of these promises have been resolved, the server side can render the components and finish the request.

"Filter" parameter as object or array

Hello)

Is it possible to create a request with like below using redux-bees?
http://localhost:3000/cities?filter[country_id]=1

I had tried
api.getCities({ filter: { country_id: countryId } })
but got only
http://localhost:3000/cities?filter=%5Bobject%20Object%5D

Can't use DELETE method for 'to-many' relationships

Hey guys great job on the module. I think I found an issue where the library isn't exactly following JSONAPI spec, though possibly I'm interpreting the spec wrong too.

I tried to do a call to an api endpoint like so { method: destroy, path: '/post/:id/relationships/comments' } with the following payload:

{
    data: [
        { type: "comments", id: "1" },
        { type: "comments", id: "2" }
   ]
}

I expected to see that these relationship records would be deleted though I ended up getting an error from my server as the body of the JSONAPI request was missing.
This is due to http method not adding the body for a DELETE request here in the destroy function, which would normally make sense apart from when you're destroying resources that are part of a 'to-many' relationship.

In the JSONAPI spec in the 'updating to-many relationships' section it says:

A server MUST respond to PATCH, POST, and DELETE requests to a URL from a to-many relationship link as described below. For all request types, the body MUST contain a data member whose value is an empty array or an array of resource identifier objects.

Obviously because the destroy method does not include the body this will not work in redux-bees. I have tried running the query in a curl request to my laravel JSONAPI server with no problem so it seems at least my PHP JSONAPI library has also interpreted the spec the same as what I have.

add credentials:'include' to call

Hello,

i am trying to get redux-bees work with a cookie authentication.
Until now it works in firefox only. I have found out, that I need to add the parameter credentials:'include' to the call. But adding it to the header parameters does not work, it needs to be outside of the header in the fetch call.
like so:

fetch('https://[ENDPOINT]', {
method: "GET",
...apiConfig,
credentials: 'include'
})

where can I slip this parameter into redux-bees so it will appear at the right position in the fetch call?

Usage with React-Redux?

I'm not really sure how to use this library with React-Redux. I've got things wired up and I can see data in the bees section of the store and request data directly from the API, but how do you use mapStateToProps and mapDispatchToProps here?

Assuming apiEndpoints includes getBee: { method: get, path: '/bee/:id' }

Ho do you expose the actions and response from the API?

mapDispatchToProps(dispatch) { 
  return({
    beeActions: bindActionCreators(/* something here */, dispatch),
  })
}

mapStateToProps(state) {
  return({
    bee: /* the bee resource (beesource, if you will) */
  })
}

And what if you're using include in the request? I see the getRelationship function in the React example, but how would you map those to the props? Is there a way to normalize that data passed into the prop? Is that what is supposed to be done?

Using Query doesn't work

Hi! I've been following the documentation and tried to pass down some props from an API call through the query decorator. However, it doesn't pass down the props. What am I missing?

To get an example, I'm using the same syntax as in the state selectors section, but with another component.

Add config option to transform body

I'm working with a python backend that I have little control over, and I receive all my server responses in snake_case.

The option for afterResolve is really helpful in this scenario so I can keep using camelCase in js and persisted state.

However for making requests, I need to provide snake_case again and it's cumbersome to convert on every single api call:

api.updatePost(
  { id: 12 }, 
  snakecaseKeys({ postId: 12, postType: 'post', postAttributes: { ... } } ),
)

It would be great to be able to set a transform on every request via the global config:

const config = {
  baseUrl: 'https://api.yourservice.com',
  transformBody(body) { 
    return snakecaseKeys(body); 
  },
  afterResolve({ status, headers, body }) {
    return Promise.resolve({ status, headers, body: camelcaseKeys(body) });
  },

And optionally override via individual configs too:

api.createWithoutSnakecase( 
  { /* placeholders */ }, 
  { /* body */ }, 
  {
    transformBody: (body) => body, 
    afterResolve: (response) => Promise.resolve(response),
  } 
)

I can take a stab at a PR if you'd like.
Thanks for the great library!

Has anyone come up with a way to update a single entity in a list?

When you have a list of items already loaded, if one of items was updated, it seems you always have to invalidate and make the request again to the whole list of resources. This is the same for a new resource being added. So a new message comes in for example, and you have to fetch ALL messages. This is how the documentation suggests you do it but it is pretty non-performance. Particular when you want to be able to patch in updates from items within a list. You don't want to be always making the API call for a whole list of things just because one of them updated.

Anyone come up with a solution for this using bees?

Cannot compile with react-create-app

I upgraded redux-bees to the latest version and now cannot compile the project, getting the following error

Failed to minify the code from this file: 
 	./node_modules/redux-bees/lib/selectors.js:57
Read more here: http://bit.ly/2tRViJ9 

http://bit.ly/2tRViJ9

Offline support

Hi, great work on this library. Is there any plan to add in offline support?

Say, when requesting data, it can serve the offline / cache version.
Or maybe to allow a callback function to do this.

Thanks in advance.

How do people handle different api calls updating the same entity

Currently the problem we have is that if we populate a list by making a query and including relationships, if somewhere else on the screen you may make a different call with different requested relationships, the top level entity is updated with the new relationship. So if your original query populated a table, for example, and accessed those relationships, things break down because now one entity in that list no longer has the relationships it originally had.

To simplify lets say you make a call to get posts with comments included. So you end up with

Get all posts with comments

entities

  • post 1
    • comments array
  • post 2
    • comments array
  • post 3
    • comments array

But on the same screen perhaps post 2 gets update via another query with a different requested shape like

Get a single individual post with author

So now your top level entities has:

entities

  • post 1
    • comments array
  • post 2
    • author
  • post 3
    comments array

So the table that was originally populated with posts and something related to comments will break because suddenly comments disappear from one of those top level posts.

How can I set mode for fetch?

the customized header cannot support mode like
configureHeaders(headers) { return { ...headers, mode: 'no-cors' } }
how can i change fetch mode there

The future of the library and other issues

Hello, Stefano!
I liked your library for interacting redux and json-api. Great work!
https://github.com/cantierecreativo/redux-bees

But I have a few questions for you, as a developer.

  • How long will you support this library?
    I would like to use your solution on my project, but I want to be sure that I will not see the library through time with status - it is not supported.

  • How confident can you use this library for prouction?
    I mean, is it well tested and will there be any drastic changes to the API in the future?

  • What browser support does your library have?
    I saw that you are using the fetch and promise method to communicate with the server. Maybe there are some other ways to communicate with the server to support older browsers.

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.