Обновление: Redux reducer не вызывается для изменения классов CSS

#javascript #arrays #reactjs #redux #react-redux

#javascript #массивы #reactjs #redux #реагировать-redux

Вопрос:

Я новичок в redux и react-redux.
Я пытаюсь изменить классы CSS, когда пользователь нажимает на <div> тег, отображаемый динамически. Код работает, когда я пытаюсь установить состояние локально, но когда я хочу использовать redux, я получаю неопределенное значение массива, в котором должно быть сохранено event.target.id . Не могли бы вы сказать мне, где я ошибаюсь? Я начну с действий:

 export const selectAttr = (e)=>{     
    return (dispatch) => {
        return(
            dispatch({
                type: SELECT_ATTRIBUTES,
                payload: e.target.id
            })
        )
    }
}
 

Reducer:

  const initialState = {
    selectedAttr: [],
}
 

export default function selectAttrReducer (state = initialState, action) {
    let tmp = [...state.selectedAttr]
    function attributes() {
        if (tmp.length === 0) {
            tmp = [...tmp, action.payload];
            return tmp;
        } else {
            for (let i = 0; i < tmp.length; i  ) {
                if (action.payload.split(":")[0] === tmp[i].split(":")[0]) {
                    tmp = [...tmp.filter(el => el.split(":")[0] !== action.payload.split(":")[0]), action.payload];

                } else {
                    tmp = [...tmp, action.payload];
                }
            }
            return tmp;
        }
    }
    switch(action.type){
        case SELECT_ATTRIBUTES:
           attributes()
            return {
                ...state,
                selectedAttr: [...state.selectedAttr, ...tmp]
            }
        default:
            return state    
    }
}
 

Фрагменты JSX:

 <div>
    {attributes.map((attr, index) => (
        <div key={attr.id}>
            {/* attribute name */}
            <p className="pdp-attr">{attr.name}:</p>

            {/* attribute representation */}
            <div className="swatch-flex">
                {attributes[index].items.map((item) => (
                    <div key={item.id}>
                        <div
                            onClick={this.props.selectAttr}
                            className={
                                selectedAttr?.indexOf(
                                    attributes[index].id.concat(":", item.id)
                                ) === -1
                                    ? "pdp-box"
                                    : "pdp-box isSelected"
                            }
                            id={attributes[index].id.concat(":", item.id)}></div>
                    </div>
                ))}
            </div>
        </div>
    ))}
</div>

const mapStateToProps = (state) => {
    return {
        selectedAttr: state.selectedAttr,
    };
};

export default connect(mapStateToProps, { selectAttr })(Component);
 

Обновить:
Похоже, что вызывается reducer, но selectedAttr array содержит тысячи элементов. Я также обновил код.
Я также использую redux-persist . Может быть, из-за этого?

Комментарии:

1. return {...state, ...tmp} Idk, какого черта будет делать объединение массива и объекта вместе, но я держу пари, что это не то, что вы хотели сделать. tmp — это список, а state — это объект. Я также беспокоюсь, что у вас есть состояние за пределами вашего редуктора. Редукторы почти всегда являются функциями состояния действия. Вытяните tmp в локальную область действия функции.

2. Если я введу tmp внутри функции throws, «‘tmp’ не определен» здесь ` ({ …state.selectedAttr, …tmp})` . Я проверил все приложение, и внутри редуктора нет состояния

3. let tmp = [...initialState.selectedAttr] нет причин, по которым это не сработает

4. @nlta Я пробовал этот способ, но те же результаты. Сейчас редуктор выглядит так. Но все равно ничего

Ответ №1:

Вы уверены, что редуктор не вызывается?

Этот код неверен:

 return {
    ...state, ...tmp
}
 

(нет)* Попробуйте это:
См. Комментарий @nlta.

 // must wrap in parenthesis to return an object
return ({
    ...state, ...tmp
})
 

Комментарии:

1. У меня есть console.log (e.target.id ) в действии, и каждый раз, когда я нажимаю на него, он регистрируется. Я также зарегистрировал реквизиты для этого компонента, и selectedAttr не определен. Я меняю код на return ({ ...state.selectedAttr, ...tmp }) , и он остается таким же. Он отображается так, как будто все теги div выбраны по умолчанию

Ответ №2:

Редуктор был вызван, но потому что это «чистая» функция (правила редукторов) Я переместил метод filter внутри селектора.