es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo asegurarme de que la llamada al backend solo se realiza después de que se ejecute setState?

En el proyecto en el que estoy trabajando actualmente hay varios de estos:

“`
const SelectOptions = ({
defaultValue,
label,
name,
options,
onChangeFilter,
multiple,
onCloseFilter
}) => {
const [option, setOption] = useState(defaultValue);

useEffect(() => {
  setOption(defaultValue);
}, [defaultValue]);

const onChangeOption = event => {
  const { value } = event.target;
  setOption(value);
  onChangeFilter(name, value);
};

return (
  <FormControl size="small" variant="outlined" fullWidth>
    <InputLabel>{label}</InputLabel>
    <Select
      label={label}
      value={option}
      onChange={onChangeOption}
      multiple={multiple}
      renderValue={selected => (multiple ? selected.join(', ') : selected)}
      MenuProps={{
        getContentAnchorEl: null
      }}
      onClose={() => onCloseFilter() }
    >
      {!multiple && <MenuItem value="">Select</MenuItem>}

      {options.map(item => (
        <MenuItem key={item} value={item}>
          {multiple && <Checkbox checked={option.includes(item)} />}
          <ListItemText primary={item} />
        </MenuItem>
      ))}
    </Select>
  </FormControl>
);

};

Estas llaman a las siguientes dos funciones en el componente padre:

const onChangeFilter = (name, value) => {
setFilters(prevState => ({ …prevState, [name]: value }));
};

const onCloseFilter = () => {
fetchData();
};

Quiero establecer todos los filtros y solo cuando cierre el &lt;Select /&gt; debe realizarse la llamada al backend para aplicar los filtros. Esto se hace a través de esta función:

const fetchData = () => {

const payload = { data: { id: record.id }, filter: { ...filters } };

mutate(
  { type: 'fetchData', resource: 'data', payload },
  {
    onSuccess: (response) => {
      setData(response.data);
    },
    onFailure: () => {
      notify('ra.notification.http_error');
    }
  }
)

};
El problema es que fetchData() se ejecuta antes de que setFilters(...) termine. No puedo ejecutar fetchData() dentro de onChangeFilter porque resultaría en demasiadas solicitudes.

¿Cómo me aseguro de que fetchData() se ejecute solo después de cerrar el <Select /> y después de que setFilters(...) actualice todos mis filtros con las opciones que elegí?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para asegurarte de que fetchData() solo se ejecute después de cerrar el <select></select> y después de que setFilters(...) haya actualizado todos tus filtros con las opciones que elegiste, puedes almacenar las opciones seleccionadas en una variable de estado en el componente padre y pasarla al componente SelectOptions como una propiedad.

    Luego, en el componente SelectOptions, puedes actualizar la variable de estado en el componente padre a través de la función onChangeFilter, lo que provocará una nueva representación del componente padre con los filtros actualizados.

    Finalmente, en el componente padre, puedes agregar una variable de estado para mantener un seguimiento de cuándo se cierra el <select></select>, y solo llamar a fetchData() cuando esta variable de estado es verdadera. Puedes actualizar esta variable de estado pasando una función de devolución de llamada a la propiedad onCloseFilter del componente SelectOptions.

    Aquí tienes un ejemplo de implementación:

    import { useState } from 'react';
    
    const ParentComponent = () => {
      const [filters, setFilters] = useState({}); // variable de estado para los filtros
      const [selectedOptions, setSelectedOptions] = useState({}); // variable de estado para las opciones seleccionadas
      const [isSelectClosed, setIsSelectClosed] = useState(false); // variable de estado para el estado del select
    
      const onChangeFilter = (name, value) => {
        setSelectedOptions(prevState => ({ ...prevState, [name]: value }));
        setFilters(prevState => ({ ...prevState, [name]: value }));
      };
    
      const onCloseFilter = () => {
        setIsSelectClosed(true);
      };
    
      const fetchData = () => {
        const payload = { data: { id: record.id }, filter: { ...filters } };
    
        // solo llamar a fetchData() cuando se cierra el select
        if (isSelectClosed) {
          mutate(
            { type: 'fetchData', resource: 'data', payload },
            {
              onSuccess: response => {
                setData(response.data);
              },
              onFailure: () => {
                notify('ra.notification.http_error');
              },
            }
          );
          setIsSelectClosed(false); // resetear el estado del select
        }
      }
    
      return (
        <div>
          <selectoptions defaultvalue="" label="Etiqueta" name="nombreFiltro" options="{opciones}" onchangefilter="{onChangeFilter}" multiple="" onclosefilter="{onCloseFilter}"></selectoptions>
        </div>
      );
    };
    
    const SelectOptions = ({
      defaultValue,
      label,
      name,
      options,
      onChangeFilter,
      multiple,
      onCloseFilter,
    }) => {
      const [option, setOption] = useState(defaultValue);
    
      const onChangeOption = event => {
        const { value } = event.target;
        setOption(value);
        onChangeFilter(name, value);
      };
    
      const handleSelectClose = () => {
        onCloseFilter();
      }
    
      return (
        <formcontrol size="small" variant="outlined" fullwidth="">
          <inputlabel>{label}</inputlabel>
          <select label="{label}" value="{option}" onchange="{onChangeOption}" multiple="{multiple}" rendervalue="{selected" ==""> (multiple ? selected.join(', ') : selected)}
            MenuProps={{
              getContentAnchorEl: null,
            }}
            onClose={handleSelectClose}
          >
            {!multiple && <menuitem value="">Seleccionar</menuitem>}
    
            {options.map(item => (
              <menuitem key="{item}" value="{item}">
                {multiple && <checkbox checked="{option.includes(item)}"></checkbox>}
                <listitemtext primary="{item}"></listitemtext>
              </menuitem>
            ))}
          </select>
        </formcontrol>
      );
    };
    

    En este ejemplo, selectedOptions es la variable de estado que contiene las opciones seleccionadas, y se actualiza cada vez que se selecciona una opción en el <select></select>. onChangeFilter actualiza tanto selectedOptions como filters con el valor y el nombre seleccionados.

    onCloseFilter establece la variable de estado de isSelectClosed en verdadero, lo que provoca una nueva representación del componente padre, y cuando se cierra el <select></select>, se llama a fetchData(), que actualiza los datos en función de los últimos filtros. Finalmente, isSelectClosed se restaura a falso.

Comments are closed.