React, Redux, как данные ответов будут доступны во всех компонентах?

Я использую реакцию и редукцию, API возвращает данные. Как данные, записанные в useDispatch, будут доступны в других компонентах.

Как customerId будет доступен во всех компонентах. Я создал код, который вызывает API, и в ответ возвращаются данные. Я также создал редуктор. Не уверен, как это сделать, чтобы customerId был доступен.

{

    "sessionId": "5f9f0de7-c7b3-3029",
    "customerId": "410742",
    "recepientId": "122",

    "keyPropertiesList": [
        {
            "id": 267076,

            "properties": {

                "customer1": {

                    "firstName": "test",

                    "lastName": "A",

                    "fullName": "test A”

                },

                "userDetail": {

                    "userId": "3770930",

                    "name": "Sam"

                },

                "locationID": "03144"

            }

        }

    ],

    "timeStamp": "2023-05-19T06:12:32Z"

}
const test = () => {
  const [sessionInfo, setsessionInfo] = useState(useSelector(state => state.app.DataReducer.sessionDetails));

  const uDispatch = useDispatch();

  useEffect(() => {
    sessionInformation();

    async function sessionInformation() {
      const session_ID = '5f9f0de7-c7b3-3029'

      console.info("sessionInformaiton: " + session_ID)

      await SessionInformationService({ sessionId: session_ID })
        .then((result) => {
          console.info("Result: " + JSON.stringify(result));

          if (result.data !== undefined) {
            setsessionInfo(result.data);
          }
        });
    }

    uDispatch(types.updateData({
      sessionDetails: {
        customerId: sessionInfo.customerId,
          customerfirstName: sessionInfo.firstName,
          customerlastName: sessionInfo.lastName,
          customerfullName: sessionInfo.fullName,
        }
      })
    );
  }, []);

  return (
    <>

    </>
  )
};

export default test;

редуктор

import * as types from './action';

export const initialState = {
  sessionDetails: {
    customerId: '',
    customerfirstName: '',
    customerlastName: '',
    customerfullName: ''
  }
}

const Datareducer = (state = initialState, action) => {
  switch (action.type) {
    case types.UPDATE_DATA:
      const output = action.payload;

      if (output.sessionDetails) {
        state.sessionDetails = output.sessionDetails;
      }

      return {
        ...state,
      }
      break;

    default:
      return state;
  }
}

export default Datareducer;

action.js

export const UPDATE_DATA = 'UPDATE_DATA';

export const updateData = payload => ({
  type: UPDATE_DATA,
  payload
});

🤔 А знаете ли вы, что...
JavaScript позволяет создавать мобильные приложения для iOS и Android с использованием фреймворков, таких как React Native и NativeScript.


1
66
1

Ответ:

Решено

Первая проблема, которую необходимо решить, — это мутация состояния в функции редуктора.

state.sessionDetails = output.sessionDetails; мутирует объект текущего состояния. Неглубоко скопируйте предыдущую ссылку на состояние, а затем переопределите свойства. Подробнее см. в разделе Неизменяемые шаблоны обновления.

const dataReducer = (state = initialState, action) => {
  switch (action.type) {
    case types.UPDATE_DATA:
      const { sessionDetails } = action.payload;

      if (sessionDetails) {
        return {
          ...state,
          sessionDetails: {
            ...state.sessionDetails,
            ...sessionDetails,
          }
        };
      }

      return state;

    default:
      return state;
  }
};

Вторая проблема заключается в том, что компонент Test неправильно управляет получением данных и обновлением хранилища. Он кэширует копию состояния sessionDetails из редукса в переменной локального состояния sessionInfo, но useEffect одновременно извлекает данные сеанса и отправляет действие updateData, которое просто отправляет необновленное sesstionInfo локальное состояние обратно в хранилище. По сути, состояние Redux не обновляется заполненными данными.

Нет необходимости в локальном sessionInfo состоянии, useEffect ловушке, выборке и отправке данных напрямую.

Компоненты React также используют имена PascalCase, test не является допустимым компонентом React, но Test является. Переименуйте функциональный компонент.

const Test = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    const sessionInformation = async () => {
      const sessionId = '5f9f0de7-c7b3-3029';

      console.info("sessionInformaiton: ", sessionId);

      try {
        const { data } = await SessionInformationService({ sessionId });

        console.info("Result: ", { data });

        if (data) {
          const userData = {
            sessionDetails: {
              customerId: data.customerId,
              firstName: data.customerfirstName,
              lastName: data.customerlastName,
              fullName: data.customerfullName,
            }
          };

          dispatch(types.updateData(userData));
        }
      } catch (error) {
        // handle any errors, if necessary, or ignore, your call
      }
    };
 
    sessionInformation();
  }, []);

  return (
    <>
      ...
    </>
  );
};

export default Test;

Используйте хук useSelector для доступа к состоянию. Функции-селекторы следуют структуре состояний, которая формируется путем объединения редюсеров.

Пример:

import { useSelector } from 'react-redux';

...

const SomeComponent = () => {
  const { customerId } = useSelector(
    state => state.app.DataReducer.sessionDetails
  );

  ...
};