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

Using state on CreateButton will polute/break other Create components #9394

Closed
ruslantalpa opened this issue Oct 26, 2023 · 6 comments · Fixed by #9407
Closed

Using state on CreateButton will polute/break other Create components #9394

ruslantalpa opened this issue Oct 26, 2023 · 6 comments · Fixed by #9407
Assignees
Labels

Comments

@ruslantalpa
Copy link

What you were expecting:
according to https://marmelab.com/react-admin/Create.html#prefilling-the-form if in any context (for example show page of an item) i render a

<CreateButton
            resource="comments"
            state={{ record: { post_id: record.id } }}
 />

This will only apply to the create form state if and only if i click this particular button.

What happened instead:
If i just visit the show page where this button is rendered, then go back to the main list of posts and click the add button (so the create form/page unrelated to comments), when clicking save, the data sent to the dataprovider (and ultimately to the api ) will contain the post_id field (invalid data which certain backends complain about with 400 bad request)

sample code
This code is not really tested (encountered the error in my own setup with custom components) but i believe it will trigger the error.

If you just click the standard "Create" button (not the custom one), The submitted form will contain post_id filed

import { List, Datagrid, TextField, DateField, BooleanField } from 'react-admin';
import { Create, SimpleForm, TextInput, DateInput, required, CreateButton, TopToolbar } from 'react-admin';
import RichTextInput from 'ra-input-rich-text';

export const PostCreate = () => (
    <Create>
        <SimpleForm>
            <TextInput source="title" validate={[required()]} fullWidth />
            <TextInput source="teaser" multiline={true} label="Short description" />
            <RichTextInput source="body" />
            <DateInput label="Publication date" source="published_at" defaultValue={new Date()} />
        </SimpleForm>
    </Create>
);

export const PostList = () => (
    <List
        actions= {
            < TopToolbar >
                <CreateButton />
                <CreateButton label="Create Comment" resource="comments" state={{ record: { post_id: 123 } }} />
            < /TopToolbar >}
    >
        <Datagrid>
            <TextField source="id" />
            <TextField source="title" />
            <DateField source="published_at" />
            <TextField source="category" />
            <BooleanField source="commentable" />
        </Datagrid>
    </List>
);

// in src/App.jsx
import { Admin, Resource } from 'react-admin';
import jsonServerProvider from 'ra-data-json-server';

import { PostList } from './posts';

const App = () => (
    <Admin dataProvider={jsonServerProvider('https://jsonplaceholder.typicode.com')}>
        <Resource name="posts" list={PostList} />
    </Admin>
);

export default App;

In essence, render a CreateButton with the state parameter and record set to something then go to any other create form (even unrelated) and the data submitted should contain the state from the custom create button.
If it is not immediately obvious and easy to reproduce, let me know and i'll look into creating a example

@ruslantalpa
Copy link
Author

Also, tried to go around this by using the to option, but the way it's described in the docs

<CreateButton
    resource="comments"
    to={{
        search: `?source=${JSON.stringify({ post_id: record.id })}`,
    }}
/>

does not work either because resource prop gets ignored so the actual url generated for the button is whatever_the_url_is_now?source=...

and that is because in this section
https://github.com/marmelab/react-admin/blob/master/packages/ra-ui-materialui/src/button/CreateButton.tsx#L65-L76

while it might look like the url is correct by setting to={createPath({ resource, type: 'create' })}
the to prop is actually overridden by {...linkParams} below which are the original to we supplied

@ruslantalpa
Copy link
Author

managed to create an example here
https://codesandbox.io/p/sandbox/thirsty-golick-4r2v8t?file=%2Fsrc%2Fcomments%2FCommentShow.tsx%3A3%2C15

i just added <CreateButton resource="comments" state={{ record: { junk: 1234 } }} /> to the comments show component.

To reproduce: open the dev tools on the console tab
go to the comments, and click on "show" for one of them (to render the button in question).
then go back to posts, and click create. create a post.
now look at the console and see something like

create posts {"data":{"average_note":0,"junk":123,"title":"asdfas","teaser":"asdfasdf","body":"<p>asdfasdf</p>","published_at":"2023-10-26T09:29:34.485Z","commentable":true,"backlinks":[{"date":"2023-10-26T09:27:52.010Z","url":"http://google.com"}]}} index.js:8:6487

notice the "junk":123

@slax57
Copy link
Contributor

slax57 commented Oct 26, 2023

Reproduced, thanks for the detailed report.

So far I have no idea where this might come from, this will require some investigation work...

@slax57 slax57 self-assigned this Oct 26, 2023
@slax57 slax57 added the bug label Oct 26, 2023
@ruslantalpa
Copy link
Author

The documentation mentions “clone” button that works the same. My guess is they will also trigger this bug.

@fzaninotto
Copy link
Member

After inspection, this regression was introduced in 4.15.0 (#9319). Fix incoming.

@ruslantalpa
Copy link
Author

Glad you guys figure it out (looked a bit at the code bug was was a bit hard to follow through all of abstractions).

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

Successfully merging a pull request may close this issue.

3 participants