简体   繁体   中英

How to dynamically set initial state variable in redux

Im trying to set the initial state of a redux state based on an object item param straight inside the redux saga state. It has to be in this file, (long story) so I decide to put it in this file. So my first thought is to write a function in the redux file to do the job. However, not sure how to access the state that I will need that is from another redux file. I did research and saw that you can use the following syntax to do so in generator functions

const state = yield select();

So I tried this in a vanilla javascript function and as expected did not work. Is there any way where I can do the following?

const initialState = {
  currentAccountId: fetchAndReturnId(),
  currentName: '',
};

function fetchAndReturnId() {
  const state = yield select();
    const { accounts } = state.global.accounts;
    const charityAccount = accounts.find(acc => acc.type === 'charity');
    return charityAccount.id;
}

Just wondering if anyone else had any other solutions. Thanks!

You can make a function for it.

Here's an example for you:

const initial = async () => {
  const id = await getId();
  const name = await getName();

  return {
    currentAccountId: id,
    currentName: name,
  };
};

Unless you do some advanced stuff like injecting reducers, what you are trying to do doesn't really make sense to me. Initial state is called "initial" because it is set BEFORE any other redux related stuff including setting any state or running any saga. So generally you can't set initalState based on other redux state, because there is no other state at the time.

That said there are some other things you can do. If you need to set the same initial state for multiple reducers you can just extract it to some constant and then use it in both places.

const INITIAL_DATA = 'foo';

const reducer1 = (state = INITIAL_DATA, action) => ...
const reducer2 = (state = INITIAL_DATA, action) => ...

If its something dynamic, like data fetched from BE, then its probably not an initial state but rather something that you would set using redux actions later in app life cycle.

const reducer = (state = null, action) => {
  if (action.type === 'FETCHED_DATA') return action.data
  return state
}

function * saga() {
  const data = yield fetchData();
  yield put({type: 'FETCHED_DATA', data});
}

Or if you have another saga, that needs to read existing redux state and then send it to reducer handling different part of the redux state you can use the select effect.

function * saga() {
  const data = yield select(getDataFromStateSlice1);
  yield put({type: 'STORE_DATA_IN_STATE_SLICE_2', data});
}

Anyway, since what you are trying to do doesn't make sense to me I am probably missing something in your question, feel free to elaborate further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM