Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrent call on CRUD endpoint issue #158

Open
divan opened this issue Jul 18, 2017 · 3 comments
Open

Concurrent call on CRUD endpoint issue #158

divan opened this issue Jul 18, 2017 · 3 comments

Comments

@divan
Copy link

divan commented Jul 18, 2017

Hi,

I'm not sure I can quickly create reproducible example, but here is the case.

I have an endpoint defined:
registrations: { url: `/api/registrations`, crud: true, transformer: transformers.array },

In one place I'm using get() to get the data:

        console.log("Getting data...");
        dispatch(rest.actions.registrations.get({}, {}, (err, data) => {
            console.log("SETTING STATE", data);
            this.setState({
                registrations: data
            })
        }));

(the original code was simpler, I was simply using props.registration.data, but then, investigating this issue, created this)

In another place (modal window) I do POST request for this endpoint:

this.props.dispatch(rest.actions.registrations.post({}, { body: JSON.stringify(data) }, (err, data) => {
            if (err != null) {
                console.log("Call failed: ", err);
                this.setState({ error: err.message });
                return
            }
        }))

So, when POST request happens, data for the first GET request is also changed.
In fact I see in console log this:

Getting data...
SETTING STATE > [Object] // which is valid data obtained with GET request
// ... modal window appears and sends POST request ...
SETTING STATE > [Object] // with object equal to result of POST: { status: "success" }

Note, that after POST request there is no "Getting data..." log entry. It looks like callback from the first action dispatch got called automagically by itself after POST request.

Any idea what I'm doing wrong here?

@lexich
Copy link
Owner

lexich commented Jul 18, 2017

Hello @divan you can't update state concurrently. In you case post request return poor json response like { status: "success" } but for redux-api it's new state. You should return new state of object with post request or write custom transformer, that doesn't rewrite state.

@thenewguy
Copy link

thenewguy commented Aug 14, 2018

I am encountering this issue as well. What is the correct way to handle this case?

One component that pulls rest data for individual records using the crud helpers. For example addresses. You need to display an origin and destination, but the api endpoint is the same. How can I hook in to use the redux-api concept? Right now, both addresses show the same data even though they fetch different ids from the remote server

    address: {
        url: '/addresses/address/:pk/?format=json',
        virtual: true,
        crud: true
    },
    getData = () => {
        const obj = this
        if (this.needData()) {
            if (this.canGetData()) {
                const params = parse_endpoint_url(this.url, endpoints.address)
                const action = rest.actions.address.get(params, {}, (error, data)=> {
                    error = error || {}
                    data = data || {}
                    obj.setState({
                        data, error
                    })
                });
                this.props.dispatch(action);
            } else {
                this.setState({
                    error: {statusText: 'Unable to get data.'}
                })
            }
        }
    }

Is it possible to keep a cached array of the last X responses? Then in select state the address can be picked by ID or refetched?

@thenewguy
Copy link

for now directly using request works but doesn't give a way to update on change

    getData = () => {
        const obj = this
        const done = (data, error) => {
            obj.setState({
                data, error
            })
        }
        if (this.needData()) {
            if (this.canGetData()) {
                const params = parse_endpoint_url(this.url, endpoints.address)
                rest.actions.address.request(params).then((data)=> {
                    done(data, {})
                }, (error) => {
                    done({}, error)
                });
            } else {
                done({}, {
                    error: {statusText: 'Unable to get data.'}
                })
            }
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants