Search code examples
javascriptreactjsreduxreact-redux

Value is coming undefined first, then is coming alright, but still receive undefined on the page render


I managed to update a boolean value from the database, but I want to get the value now in the interface, so the user will see exactly the value from the database.

I did this using redux, so here it's my action:

export const getSettings = () => async (dispatch) => {
  dispatch({ type: CHANGE_SETTINGS_REQUEST, payload: {} });
  try {
    const { data } = await Axios.get(
      "http://localhost:3030/v1/lootbox/getSettings"
    );
    dispatch({ type: CHANGE_SETTINGS_SUCCESS, payload: data });
    localStorage.setItem("changeSettingsInfo", JSON.stringify(data));
  } catch (error) {
    dispatch({
      type: CHANGE_SETTINGS_FAIL,
      payload:
        error.response && error.response.data.message
          ? error.response.data.message
          : error.message,
    });
  }
};

In the component I have the following:

import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { changeSettings, getSettings } from "../../actions/adminActions";
import MessageBox from "../../components/ErrorBox/MessageBox";
import LoadingBox from "../../components/Spinner/LoadingBox";

export default function LootboxSettings() {
  const getSetting = useSelector((state) => state.getSetting);
  const { changeSettingsInfo, loading, error } = getSetting;
  const [checked, setChecked] = useState(changeSettingsInfo?.isVisible);

  const dispatch = useDispatch();

  const handleCheck = () => {
    setChecked(!checked);
  };

  const submitHandler = (e) => {
    e.preventDefault();
    dispatch(changeSettings(checked));
  };

  useEffect(() => {
    dispatch(getSettings());
  }, []);

  return (
    <>
      <div className='login'>Lootbox Settings</div>
      {changeSettingsInfo && (
        <form className='swapping-currency-checkbox' onSubmit={submitHandler}>
          {loading && <LoadingBox></LoadingBox>}
          {error && <MessageBox variant='danger'>{error}</MessageBox>}
          <label>Is lootbox visible?</label>
          <input
            type='checkbox'
            className='swapping-currency-check'
            id='location'
            name='location'
            checked={checked}
            onChange={handleCheck}
            value='checkbox'
          />
          <div>
            <button className='buttonAccount swapping-btn' type='submit'>
              Save
            </button>
          </div>
        </form>
      )}
    </>
  );
}

So if I console.log changeSettingsInfo, I'm getting undefined and then the boolean value from the database(that's why I used the ? optional parameter), if i delete the optional I get an error, because it is undefined, here are the logs:

enter image description here

Something I'm doing wrong, but I don't know what, maybe on the useEffect. What can i do?


Solution

  • Try this to reflect change:

    useEffect(() => {
        setChecked(changeSettingsInfo?.isVisible);
    }, [changeSettingsInfo]);
    

    Explaination:

    The UI is binded by a local state variable which is initialized when a component mounts. The dispatch triggers a change on the store, whose values are passed as props to the functional component. Causing a re-render on the UI. In your case your console still prints undefined for state variable checked because quite frankly on re-rendering of the component you are not setting the value for checked So in order to do that, create a specialized useEffect that triggers whenever the value of your variable changeSettingsInfo changes.