javascript - React useState with ES6 classes - Stack Overflow

I want to create a form to save some form of data model in a database.Let's say I have a class:e

I want to create a form to save some form of data model in a database.

Let's say I have a class:

export default class Model {
    constructor(model = {}) {
        this.x = model.x || '';
        this.y = model.y || '';
    }
    save() {
        // code to save 'this' to database
    }

}

And a ponent:

import { React, useState } from 'react';
   
export const ModelForm = () => {
    const [model, setModel] = useState(new Model());

    const handleInputChange = (event) => {
        const target = event.target;

        setModel({ ...model, [target.name]: target.value });
    };

    const handleSubmit = (event) => {
        event.preventDefault();
        const modelObject = new Model(model);
        modelObject.save();
    };

    return (
        <form onSubmit={handleSubmit}>
            <input type='text' name='x' value={model.x} onChange={handleInputChange} />
            <input type='text' name='y' value={model.y} onChange={handleInputChange} />
            <button type='submit'>Submit</button>
        </form>
    );
};

This thing is currently working, but I have a question.

Every time I do setModel, I have to destructure the model object and change the value accordingly. Since I destructure it, when I am submitting the form, the object in the ponent is no longer a Model object, but a simple javascript Object. So, as you can see, I have to create a new one to use save() on it.

Is my approach good or there is a better way to do it?

Also, is it a good practice to use ES6 classes in useState? Are there any downfalls?

I want to create a form to save some form of data model in a database.

Let's say I have a class:

export default class Model {
    constructor(model = {}) {
        this.x = model.x || '';
        this.y = model.y || '';
    }
    save() {
        // code to save 'this' to database
    }

}

And a ponent:

import { React, useState } from 'react';
   
export const ModelForm = () => {
    const [model, setModel] = useState(new Model());

    const handleInputChange = (event) => {
        const target = event.target;

        setModel({ ...model, [target.name]: target.value });
    };

    const handleSubmit = (event) => {
        event.preventDefault();
        const modelObject = new Model(model);
        modelObject.save();
    };

    return (
        <form onSubmit={handleSubmit}>
            <input type='text' name='x' value={model.x} onChange={handleInputChange} />
            <input type='text' name='y' value={model.y} onChange={handleInputChange} />
            <button type='submit'>Submit</button>
        </form>
    );
};

This thing is currently working, but I have a question.

Every time I do setModel, I have to destructure the model object and change the value accordingly. Since I destructure it, when I am submitting the form, the object in the ponent is no longer a Model object, but a simple javascript Object. So, as you can see, I have to create a new one to use save() on it.

Is my approach good or there is a better way to do it?

Also, is it a good practice to use ES6 classes in useState? Are there any downfalls?

Share Improve this question edited Jun 18, 2021 at 13:30 Ghost asked Jun 18, 2021 at 13:25 GhostGhost 4076 silver badges19 bronze badges 9
  • 1 I would change it so that Model is not responsible for the saving to database. I don't think the saving needs to be coupled to the model at all. It would also solve this 'problem' of having to re-create the Model – nbokmans Commented Jun 18, 2021 at 13:28
  • @nbokmans Ok, I understand. Other than that, is it a good practice to use ES6 classes in useState? Are there any downfalls? – Ghost Commented Jun 18, 2021 at 13:30
  • 1 @MedetTleukabiluly why? – Ghost Commented Jun 18, 2021 at 13:33
  • 1 Because your state will change a lot because functions are not primitives - react works on primitive state, and it will require ponent re-render – Medet Tleukabiluly Commented Jun 18, 2021 at 13:34
  • 1 @MedetTleukabiluly Class methods don't change. And actually react doesn't do deep equality checks on state, so it won't even consider the methods - what matter is whether you pass a different instance or not. – Bergi Commented Jun 18, 2021 at 13:54
 |  Show 4 more ments

3 Answers 3

Reset to default 3

I have to create a [new Model] to use save() on it.

That's certainly a viable approach. You wouldn't actually store a Model instance in your state, but only the options object for your constructor. Initialise it as simply

const [model, setModel] = useState({});

(and possibly rename it to modelArgs or modelOptions)

Since I destructure it, […] the object in the ponent [state] is no longer a Model object, but a simple javascript Object.

It's actually not destructuring, rather object literal spread syntax, but yes - you're creating a plain object in your setModel call.

To fix the problem, you'd need to pass a model instance there - a new one, since React state is designed around immutability. You can easily achieve that though:

export default class Model {
    constructor(model = {}) {
        this.x = model.x || '';
        this.y = model.y || '';
    }
    withUpdate({name, value}) {
        // if (!['x', 'y'].includes(name)) throw new RangeError(…)
        return new Model({...this, [name]: value});
        // or optimised (?):
        const clone = new Model(this);
        clone[name] = value;
        return clone;
    }
    save() {
        // code to save 'this' to database
    }

}
const [model, setModel] = useState(new Model());
const handleInputChange = (event) => {
    setModel(model.withUpdate(event.target));
};

In my personal opinion, I don't think using ES6 classes in the state is a good idea. In fact, in the react useState hook documentation say that if you need to have two states on your ponent you should put two useState hooks.

// If there are too many states, you can use useReducer hook
const [state1, setState1] = useState();
const [state2, setState2] = useState();

I prefer use the useState hooks with primitives values, because as React works, when you change the state, if the value of the new state is equal to the old one, the ponent doesn't re-render because react do that parison by itself, but when you use a object or any other non primitive value, even if the props of the object and values are the same, the reference to that object is going to be different, so it will re-render when it should not. Remember that when JavaScript pares non primitive values it pares its references in memory so:

const obj1 = {prop: 'a'};
const obj2 = {prop: 'a'};
console.log(obj1 === obj2); // This logs false because they are different objects and they references in memory are not equal
console.log(obj1 === obj1); // This logs true, because its reference is the same.
console.log(obj1.prop === obj2.prop); // This logs true because they are strings (primitive values)

I agree that it is very usefull to have es6 classes in your state sometimes. A decent solution is just to create a derived variable.

import { React, useState } from 'react';
   
export const ModelForm = () => {
    const [_model, setModel] = useState({});
    const model = new Model(_model)

    const handleInputChange = (event) => {
        const target = event.target;

        setModel({ ...model, [target.name]: target.value });
    };

    const handleSubmit = (event) => {
        event.preventDefault();
        const modelObject = new Model(model);
        modelObject.save();
    };

    return (
        <form onSubmit={handleSubmit}>
            <input type='text' name='x' value={model.x} onChange={handleInputChange} />
            <input type='text' name='y' value={model.y} onChange={handleInputChange} />
            <button type='submit'>Submit</button>
        </form>
    );
};

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745589071a4634723.html

相关推荐

  • javascript - React useState with ES6 classes - Stack Overflow

    I want to create a form to save some form of data model in a database.Let's say I have a class:e

    9小时前
    30

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信