> For the complete documentation index, see [llms.txt](https://manu-artero-anguita.gitbook.io/buenas-practicas-con-react/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://manu-artero-anguita.gitbook.io/buenas-practicas-con-react/sesion-3/6.-principios-solid.md).

# 6. Principios SOLID

{% file src="/files/B64FibxRmPhqIWqzGyBn" %}
*Martin, Robert C. (2000).* [*"Design Principles and Design Patterns"*](https://web.archive.org/web/20150906155800/http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf)
{% endfile %}

### Single Responsibility Principle

Every element should do exactly one thing

{% hint style="success" %}
React: **Presentation** & **Container** components
{% endhint %}

{% tabs %}
{% tab title="Initial code" %}

```jsx
function Users() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users", { method: "GET" })
      .then((response) => response.json())
      .then(setUsers);
  }, []);

  return (
    <section>
      <h1>Users: </h1>
      <ul>
        {users.map((user) => (
          <li>{user.username}</li>
        ))}
      </ul>
    </section>
  );
}
```

{% endtab %}

{% tab title="=> Presentation component" %}

```jsx
function Users({ users }) {
  return (
    <section>
      <h1>Users: </h1>
      <ul>
        {users.map((user) => (
          <li key={`user-${user.username}`}>{user.username}</li>
        ))}
      </ul>
    </section>
  );
}
```

{% endtab %}

{% tab title="=> Container component" %}

```jsx
function UsersContainer() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users", { method: "GET" })
      .then((response) => response.json())
      .then(setUsers);
  }, []);

  return <Users users={users} />;
}
```

{% endtab %}
{% endtabs %}

### Open/Close Principle

You should be able to add functionality to some module, without modifying its existing source code

{% hint style="info" %}
Composición >>> Herencia
{% endhint %}

{% hint style="success" %}
React: división en **componentes**&#x20;
{% endhint %}

{% tabs %}
{% tab title="Container component" %}

```jsx
function UsersContainer() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users", { method: "GET" })
      .then((response) => response.json())
      .then(setUsers);
  }, []);

  return <Users users={users} />;
}
```

{% endtab %}

{% tab title="=> composition component" %}

```jsx
function Users({ users }) {
  return (
    <section>
      <h1>Users: </h1>
      <ul>
        {users.map((user) => (
          <User user={user} />
        ))}
      </ul>
    </section>
  );
}

function User({ user }) {
  return (
   <article key={`user-${user.username}`} className="user">
      <span>{user.username}</span>
      <div className="user__contact-info">
        {user.company.name}
        {user.email}
      </div>
    </article>
  );
}
```

{% endtab %}
{% endtabs %}

### Substitution Principle (Liskov)

{% hint style="info" %}
Cualquier objeto se tiene que poder sustituir por un objeto que sea un subconjunto
{% endhint %}

{% hint style="success" %}
React: Las propiedades de los components representan su API
{% endhint %}

```diff
function Users({ users }) {
  return (
    <section>
      <h1>Users: </h1>
      <ul>
        {users.map((user) => (
-          <User user={user} />
+          <UserCard user={user} />
        ))}
      </ul>
    </section>
  );
}
```

### Interface Segregation Principle

{% hint style="info" %}
No fuerces cumplir interfaces que no se usen.
{% endhint %}

{% hint style="success" %}
React: Lista solo las propiedades necesarias (no dependas de propiedades que no necesitas)
{% endhint %}

```diff
-function UserCard({ user }) {
+function UserCard({ username, company, email }) {
```

### Dependency Inversion Principle <a href="#dependency-inversion-principle-dip" id="dependency-inversion-principle-dip"></a>

{% hint style="info" %}
Interacciona con los detalles usando abstracciones
{% endhint %}

{% hint style="success" %}
React: Extracción a custom hooks
{% endhint %}

{% tabs %}
{% tab title="custom hook" %}

```jsx
function useUsers() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    let isSubscribed = true;

    api.fetchUsers().then((users) => {
      if (isSubscribed) {
        setUsers(users);
      }
    });

    const cleanUp = () => {
      isSubscribed = false;
    };
    return cleanUp;
  }, []);

  return { users };
}

function UsersContainer() {
  const { users } = useUsers();

  return <Users users={users} />;
}
```

{% endtab %}

{% tab title="container component: no entra en el detalle" %}

```jsx
function UsersContainer() {
  const { users } = useUsers();

  return <Users users={users} />;
}
```

{% endtab %}
{% endtabs %}
