the ugly organization - lifts front-end

desu

Thx, aun no estoy del todo contento con la UI de visualización.

Este ejemplo que tengo fichado me gusta bastante, porque cada ejercicio es un bloque, y cada fila dentro del bloque es una serie... entonces como mas largo sea mas volumen tiene ese dia... Me parece muy interesante visualizar asi el trabajo de cada semana. Lo de poner los discos no me gusta nada jaja no se porque lo hace la gente.

Tambien se ve bastante bonito este ejemplo de UI visualmente.

En mi caso como mis plantillas los tengo ya seleccionados y uso la herramienta para ver que me toca cada dia no me importa mucho, pero si por ejemplo quiero permitir en el futuro a los usuarios a configurar su propio entreno, esta visualización me parece muy top para ello. Le añadiría un index de stress en el ciclo y la vista de mesos que estuve preparando:

Si metes un par de utilities de este estilo te queda una app para programar entrenos y hacer seguimiento para entrenadores muy buena. Crear semanas y dias, cada dia pones ejercicios y seleccionas las series/repes y el peso que puede ser RPE o RM por ejemplo...

Otra idea que tengo es que se pueda compartir el entreno, aun no tengo lo de guardar el estado de tus pesos y tal, con esa información podria generar un hash y meterlo a la url: https://lifts-two.vercel.app/share?id=SOME_HASH_HERE_1234

Que de hecho podria ser tan fácil para empezar como: https://lifts-two.vercel.app/share?template=1&bp=120&sq=140&dl=160&wpu=105&ohp=80 y a tomar por culo, al cargar leo los query params.

liebgott
export function UserConfigProvider({ children }: { children: React.ReactNode }) {
  const exercises = new Map<ExerciseType, [number, Dispatch<SetStateAction<number>>]>();
  exercises.set(ExerciseType.BENCH_PRESS, useState<number>(103));
  exercises.set(ExerciseType.BACK_SQUAT, useState<number>(110));
  exercises.set(ExerciseType.WEIGHTED_PULLUPS, useState<number>(116));
  exercises.set(ExerciseType.DL, useState<number>(120));
  exercises.set(ExerciseType.OHP, useState<number>(70));

  const lastExercises = new Map<ExerciseType, [number, Dispatch<SetStateAction<number>>]>();
  lastExercises.set(ExerciseType.BENCH_PRESS, useState<number>(0));
  lastExercises.set(ExerciseType.BACK_SQUAT, useState<number>(0));
  lastExercises.set(ExerciseType.WEIGHTED_PULLUPS, useState<number>(0));
  lastExercises.set(ExerciseType.DL, useState<number>(0));
  lastExercises.set(ExerciseType.OHP, useState<number>(0));

  const use90tm = useState<boolean>(false);

  const userConfig: UserConfig = {
    exercises,
    use90tm,
    lastExercises,
  };

  return (
    <UserConfigContext.Provider value={userConfig}>
      {children}
    </UserConfigContext.Provider>
  );
}

Me sorprende que esto funcione, ¿no estas usando linters? Esos hooks deberían estar en el top level del componente y ser inicializados ahi antes de meterlo en el Map. Also, xq usas un Map, un simple objeto no te vale?

React nunca se penso para ser mas alla de una libreria que proporcionase updates eficientes de UI via one-way data bindings y VDOM. Este approach era radicalmente más eficiente y proporcionaba una mejor DX (y ademas era muchisimo más fácil de aprender) que lo que se usaba por entonces, básicamente Angular y su monstruosa strong opinions en todo (servicios, controladores, etc), lo que le hacia tremendamente inapropiado para dos cosas fundamentales en aquellos años de dinero gratis: iterar rápido y que cualquier pelagatos que ficharas fuera "eficiente" montando una UI. En este sentido fue todo un exito. El "problema" es que no te proporcionaba nada a nivel de arquitectura, data handling, etc, de ahi que se iterara cn movidas cn Flux y luego Redux. Ademas, el paradigma de reducers en UI es super facil de entender y prototipar con el, de ahi su exito. Y precisamente ser TAN EXPLICITO proporcionaba una clara vision de la app solo viendo la store.

useState y useReducer no deberian ser usados para estados globales, no se pensaron para eso. useReducer es sugar syntax alrededor de useState para hacerlo más eficiente y cercano al paradigma imperante, Redux, y ni siquiera eso, ya q React tiene cierta capacidad de batching cuando se encuentra con varios useState seguidos.

Para estados globales, incluso para estado de componente, hoy en dia se usa Jotai o Zustand, que no requieren Providers.

Se ha pretendido convertir a React en algo que NO es, de ahi el monton de mierda que se sta comiendo ultimanete. Hasta que salga 19, si es hoy en dia un pifostio importante que obliga al dev a pensar constamente en microoptimizaciones (useCallback y useMemo) y hacer cosas mierders, xq su paradigma ya esta mas q agotado, de ahi que Facebook pase ya de el y se lo haya "cedido" a Vercel practicamente.

Paralelamente hay cosas radicalmente diferentes como Svelte o SolidJS, especialmente Svelte que es sexo duro, que deprecan la DX de React.

Also en

https://github.com/vrnvu/lifts/blob/master/src/components/Benchmark.tsx,

podrias hacer un custom hook para get/set sin necesidad de escribir tanto codigo, incluso si atomizaras eso cn Jotai por ejemplo, te quedaria mejor. Sin olvidar que toda esa computacion se va a repetir una y otra vez en cada render, quizas si seria adecuado meter useCallback y useMemo

1 1 respuesta
desu
#32liebgott:

Esos hooks deberían estar en el top level del componente y ser inicializados ahi antes de meterlo en el Map

En javascript, y mayoria de langs, no hay ningún problema en escapar una referencia del stack a la heap. El compilador/transpiler/bundler lo que sea que haga magia negra te lo mueve. Si que en C y CPP te hace undefined, y en Rust no compilara.

Desconocía que era buena practica tener la referencia global, uso el linter de vscode sin nada extra, asi que no me debe marcar todo.

Lo he cambiado.

#32liebgott:

Also, xq usas un Map, un simple objeto no te vale?

Me pareció mas simple para empezar.

Si en lugar de tengo un map tengo un objeto me cambia que no puedo tener enums numericos, y no me gusta, aunque sea una micro-optimizacion que en js tenga poco sentido jaja es mania.

https://github.com/vrnvu/lifts/commit/5d44fca1264472626e832f5b63bb6c865ee66da6

#32liebgott:

hoy en dia se usa Jotai o Zustand

He mirado zustand esta tarde pero no me gusta, entiendo que tiene beneficios al tener el curry a la hora de re-renderizar o no que comentas, pero a nivel de codigo no me gusta mover el código de la scope global a un curry.

Por ejemplo:

export function getWeight(userConfig: UserConfig, exercise: ExerciseType): number {
  return userConfig.exercises[exercise][0];
}

Esta función debería estar dentro de mi store:

const useUserExercisesStore = create<State & Action>((set) => ({
  ex1: 123,
  ex2: 1234,
  updateEx1: (v) => set(() => ({ ex1: v })),
  updateEx2: (v) => set(() => ({ ex2: v })),
  getWeight: (ex) => // no se como seria ahora mismo referenciar las keys del set, set.ex?
}))

La verdad, no me gusta como react mueve todo dentro de los hooks y hace curry de todo, como bien dices tiene sus motivos históricos para optimizar el dom y los refrescos, y me parece interesante tu aporte, a nivel yo de hacer mi proyecto for fun, prefiero tenerlo global.

No se si me dejo algo o hay otro motivo por el cual debería moverlo dentro del curry.

#32liebgott:

Paralelamente hay cosas radicalmente diferentes como Svelte o SolidJS, especialmente Svelte que es sexo duro, que deprecan la DX de React.

Si, he usado nextjs en el trabajo. Y para hacer mis proyectos probe React, Astro, Remix, Vue. Y creo que me dejo 1 mas. Me gustaron astro y remix pero como igualmente necesitaba librerías de componentes y usar algo como React tire por ahi.

Remix creo que es el que usa un approach differente al hacer llamadas y cargar la pagina, si no es Remix es el que no me acuerdo, muy interesante.

#32liebgott:

podrias hacer un custom hook para get/set

Si lo tengo hecho pero no lo he usado porque no lo refactorize jaja No es un custom hook porque no uso react, pero vamos, tenia funciones auxiliares que en lugar de hook le paso la referencia del state y pista.

export function updateLastWeight(userConfig: UserConfig, exercise: ExerciseType): Dispatch<SetStateAction<number>> {
   return userConfig.lastExercises.get(exercise)![1];
 }

tenia estos updates, como dices no los uso, el codigo no esta muy refactorizado y por ejemplo los componentes de Card que uso los tengo que re-hacer en algun momento. Pero cuando empece el proyecto no sabría que necesitaría asi que no podia re-factorizar sin hacer primero las pruebas.

Una cosa que si me gusta del objeto y que quería tener para el estado es que es mas fácil de serializar, para cuando meta el localstorage. Lo que aun no me he decidido que quiero guardar porque tengo 2-3 ideas de visualización.

Ah, y a mi angular me parece mil veces mejor que React. Pero de calle. Solo con el doble binding una store global que te la picas tu a mano sin problema y a volar.

3