#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 внутри селектора.