Unknown developer
Unknown developer

Reputation: 5950

Using data models to handle API responses

I'd like to ask if it is beneficial to model the API response on the client. To be more specific:

First approach:

const [formData, setFormData] = useState(null);
...
useEffect(() => {
    const callback = async () => {
      try {
        const fetchData = await axios.get(...);
        setFormData(fetchData.data);
      } catch (e) {
        ...
      }
    };
    callback();
  }, []);


return(
<Form>
  <Input name="first name" value={formData.firstName}/>
  <Input name="last name" value={formData.lastName}/>
</Form>
)

Second approach:

const [formData, setFormData] = useState(new FormModel());
...
useEffect(() => {
    const callback = async () => {
      try {
        const fetchData = await axios.get(...);
        setFormData(...formData, fetchData.data);
      } catch (e) {
        ...
      }
    };
    callback();
  }, []);


return(
<Form>
  <Input name="first name" value={formData.firstName}/>
  <Input name="last name" value={formData.lastName}/>
</Form>
)

where FormModel has already been defined in another file like:

export class FormModel {
  firstName: string = undefined;
  lastName: string = undefined;
}

Is it the second approach more beneficial and why? Do we need to model the data fetched from the server? Wouldn't it be the same using an interface for formData in the first approach instead of implementing the second one?

P.S. The second approach might not make big difference from the first one. However, have seen many times that UI creates models for managing data fetched/sent from/to the server and wondering what are the real benefits we get.

Upvotes: 3

Views: 1321

Answers (3)

ShinaBR2
ShinaBR2

Reputation: 2705

One thing I need to mention, please ignore TypeScript part, because it is just a compiler, with or without TypeScript, it does not matter to my answer and my big picture I will show you.

It seems you're a front-end developer. The quick answer should be: the second approach is my preferred and the way a frontend developer should do. It has some benefits are:

  • It force frontend has a strict data structure itself. Please note, "data structure" does not mean TypeScript types or interfaces. The data structure is the first thing every developer should think about.
  • When you have that "model" on the client-side, you can create a "mapping function" to map "what you get from backend" to your that "model". This thing has a crucial advantage is: you just need to change only mapping function, everything else on frontend should work automatically.
  • If you are working with a REST backend, you will see my above point because you can not control what exact data structure to be responded. REST does not have a way itself to control data between the client-side and server-side. And you can not trust in your back-end developers, because humans always make mistakes.

If you are using GraphQL instead of REST, you will never ask this question again because of its strict type of GraphQL. And GraphQL should be the future for API, that should be the way client-side and server-sider communicates. This is a bigger picture for you.

Upvotes: 0

Black Hole
Black Hole

Reputation: 1382

If you know the server responses, you can simple pass the object so you can make a file with all objects that you will need, and you can assign defaults values if you wich, is the more simplest way to replicate the typed as TypeScript, of course you need more things

const formExampleModel = {
  firstName: '',
  lastName: ''
}

const [formData, setFormData] = useState(formExampleModel);
...
useEffect(() => {
    const callback = async () => {
      try {
        const fetchData = await axios.get(...);
        // Here comes the trick, you can choose if you want save the initials value 
        // or replace all, so you can use 
        // setFormData(fetchData.data) -> to replace all
        // setFormData(prev => ({...prev, fetchData.data})) -> to keep no matches data
        setFormData(fetchData.data);
      } catch (e) {
        ...
      }
    };
    callback();
  }, []);


return(
<Form>
  <Input name="first name" value={formData.firstName}/>
  <Input name="last name" value={formData.lastName}/>
</Form>
)

Upvotes: 0

Mordechai
Mordechai

Reputation: 16284

Depends on what you consider beneficial in your business problem.

The second approach will start with a default value, which might be beneficial as an interim display value; and will keep old field values that are not in the response, which might or might not be beneficial in your case. That all.

Unless you use TypeScript, no one will enforce any model rules.

BTW you should modify your code to:

setFormData(prev => ({...prev, fetchData.data}));

Otherwise React will complain about a missing effect dependency.

Upvotes: 1

Related Questions