1

I got same component with Antd form for add/edit article. With pathes in router

<Route path="/add" component={ !currentUser ? Login : ArticleEditor } />
<Route path="/article/:id/edit" component={ !currentUser ? Login : ArticleEditor } />

When I click "edit" button I add initialValues to form, than if I click "Create new article" url changes to "/add", but form didn't update values. Values remains from edited article. How to update form values? Tried to set initialValues depends at path, or "id" but its not worked. How to update antd form values in that case?

const initialValues = this.props.location.pathname === '/add' ? {} : {
      title: this.props?.title,
      body: this.props?.body,
      description: this.props?.description
    };

Here you can see the component code - codesandbox link

Will Black
  • 350
  • 2
  • 17

2 Answers2

1

The main issue with the code is form fields are not reset when url is changed, you can detect path change in shouldComponentUpdate and set isLoading to true and rest should work.

Updating initialValues will not work because, antd does shallow compare and once initialValues are set, you will not be able to change them.

There was an issue in the logic of componentDidUpdate which I corrected as well.

import React from "react";
import ErrorsList from "../ErrorsList/ErrorsList";
import userService from "../../services/userService";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import { Form, Input, Button } from "antd";
import { store } from "../../store";
import actionCreators from "../../actionCreators";

const formItemLayout = {
  labelCol: { span: 24 },
  wrapperCol: { span: 24 }
};

const formSingleItemLayout = {
  wrapperCol: { span: 24, offset: 0 }
};

const mapStateToProps = (state) => ({
  ...state.editor
});

const mapDispatchToProps = (dispatch) => ({
  onLoad: (payload) => dispatch(actionCreators.doEditorLoaded(payload)),
  onUnload: () => dispatch(actionCreators.doEditorUnloaded()),
  onUpdateField: (key, value) =>
    dispatch(actionCreators.doUpdateFieldEditor(key, value)),
  onSubmit: (payload, slug) => {
    dispatch(actionCreators.doArticleSubmitted(payload));
    store.dispatch(push(`/`)); //article/${slug}
  },
  onRedirect: () => dispatch(actionCreators.doRedirect())
});

class ArticleEditor extends React.Component {
  constructor(props) {
    super(props);
    this.id = this.props.match.params.id;
    const updateFieldEvent = (key) => (e) =>
      this.props.onUpdateField(key, e.target.value);
    this.changeTitle = updateFieldEvent("title");
    this.changeDescription = updateFieldEvent("description");
    this.changeBody = updateFieldEvent("body");
    this.changeTagInput = updateFieldEvent("tagInput");
    this.isLoading = true;

    this.submitForm = () => {
      const article = {
        title: this.props.title,
        description: this.props.description,
        body: this.props.body,
        tagList: this.props.tagInput.split(",")
      };

      const slug = { slug: this.props.articleSlug };
      const promise = this.props.articleSlug
        ? userService.articles.update(Object.assign(article, slug))
        : userService.articles.create(article);

      this.props.onSubmit(promise, this.props.articleSlug);
    };
  }

  componentDidUpdate(prevProps, prevState) {
    if (this.props.match.params.id !== prevProps.match.params.id) {
      if (prevProps.match.params.id) {
        this.props.onUnload();
      }

      this.id = this.props.match.params.id;
      if (this.id) {
        return this.props.onLoad(userService.articles.get(this.id));
      }

      this.props.onLoad(null);
    }

    this.isLoading = false;
  }

  componentDidMount() {
    if (this.id) {
      this.isLoading = true;
      return this.props.onLoad(userService.articles.get(this.id));
    }
    this.isLoading = false;
    this.props.onLoad(null);
  }

  componentWillUnmount() {
    this.props.onUnload();
  }

  shouldComponentUpdate(newProps, newState) {
    if (this.props.match.params.id !== newProps.match.params.id) {
      this.isLoading = true;
    }

    return true;
  }

  render() {
    const { errors } = this.props;
    const initialValues = {
      title: this.props?.title,
      body: this.props?.body,
      description: this.props?.description,
      tags: this.props?.tagList
    };

    return this.isLoading ? (
      "loading..."
    ) : (
      <div className="editor-page">
        <div className="container page">
          <div className="">
            <div className="">
              <ErrorsList errors={errors}></ErrorsList>
              <Form
                {...formItemLayout}
                initialValues={initialValues}
                onFinish={this.submitForm}
              >
                <Form.Item
                  label="Title"
                  name="title"
                  placeholder="Article Title"
                  rules={[
                    {
                      required: true,
                      message: "Please input article title"
                    }
                  ]}
                >
                  <Input onChange={this.changeTitle} />
                </Form.Item>
                <Form.Item
                  label="Description"
                  name="description"
                  placeholder="Short description"
                  rules={[
                    {
                      required: true,
                      message: "Please input article description"
                    }
                  ]}
                >
                  <Input onChange={this.changeDescription} />
                </Form.Item>
                <Form.Item
                  name="body"
                  label="Article Text"
                  placeholder="article text"
                >
                  <Input.TextArea onChange={this.changeBody} />
                </Form.Item>
                <Form.Item name="tags" label="Tags" placeholder="Enter tags">
                  <Input onChange={this.changeTagInput} />
                </Form.Item>
                <Form.Item {...formSingleItemLayout}>
                  <Button
                    className="editor-form__btn"
                    type="primary"
                    htmlType="submit"
                    disabled={this.props.inProgress}
                  >
                    Submit Article
                  </Button>
                </Form.Item>
              </Form>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

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

take a look at this forked codesandbox.

Dipen Shah
  • 25,562
  • 1
  • 32
  • 58
1

You have to clean the fields before you re-use the 'ArticleEditor' component. Here you are using the same component for two different route, hence it's not changing.

You have to check if you are editing or adding a new entry to the Editor. Your editor component may look like this then,

const ArticleEditor = props => {
   const [form] = Form.useForm();
   useEffect(() => {
      if (props.match.params.id) form.setFieldsValue({value : 'Some values'})
      else form.resetFields()
   }, [props?.match?.params]);

   return (
      <Form form={form} onFinish={yourFinishMethod}>
          //...your form fields
      </Form>
   )
}
shahriar hasan
  • 113
  • 1
  • 3
  • 10