我如何 select/unselect 在 redux 中?

How do I select/unselect in redux?

我有一份培训师名单,我必须 select 和取消 select 它们作为切换按钮。下面是这样做的代码,但我不知道如何正确实现它。

操作:

 const selectTrainer = (selected) => ({
    type: 'SELECT_TRAINER',
    payload: {
      
      selected: selected
    }
  });

培训师:

function Trainer(props) {

  const [addBtnToggle, setBtnToggle] = useState(false);

  return (
    <>
      
        {addBtnToggle ?  <button onClick={() => setBtnToggle(!addBtnToggle)}>Selected</button> : <button onClick={() => setBtnToggle(!addBtnToggle)}>Select</button> }
        {addBtnToggle && <Select />}
    </>
  );
}

export default Trainer;

减速器:

import {v4 as uuid} from 'uuid';
const initalState = [
  {
    id: uuid(),
    name: '',
    team: [],
    selected: false
  }
];

let copyState = null;
let index = 0;

const trainerReducer = (state = initalState, action) => {
  const {type, payload} = action
   
    case "SELECT_TRAINER":
      return state.map((trainer) => 
        trainer.id === payload.id ? trainer.selected = true : trainer
      );


    default:
      return state;
  }
};

export default trainerReducer;

Select:

function Select() {
    const dispatch = useDispatch();
    const allTrainers = useSelector((state) => state.trainers);
    allTrainers.map(a => a.selected===true );
  
    const arr = []
    arr.push(props.data.name)
    console.log(result)
    dispatch(actions.selectTrainer());
    return null
}
export default Select;

如何添加一个开关以取消select一个特定的项目,以及如何在我想select另一个项目时取消select已经selected的项目项目?

当使用我所说的遗留减速器(即pre-redux-toolkit)时,您需要应用Immutable Update Pattern。 reducer 函数正确地创建了 state 数组的浅拷贝,但它还需要浅拷贝它正在更新的任何嵌套状态。在这种情况下,它应该使用 copied/updated 属性创建一个新的“trainer”对象引用。

示例:

const initialState = [
  {
    id: uuid(),
    name: '',
    team: [],
    selected: false
  }
];

const trainerReducer = (state = initialState, action) => {
  const {type, payload} = action
  
  switch(type) { 
    case "SELECT_TRAINER":
      return state.map((trainer) => // <-- shallow copy array
        trainer.id === payload.id
          ? {                 // <-- new object reference
              ...trainer,     // <-- shallow copy trainer properties
              selected: true, // <-- overwrite property with new value
            } 
          : trainer
      );

    ... other cases...

    default:
      return state;
  }
};

How do I add a toggle to unselect a particular item and how do I unselect the already selected item when I want to select another item?

这听起来好像您只需要一个选定的培训师。您可以更新 reducer case 以检查是否选择了当前训练对象并取消选择它。

case "SELECT_TRAINER":
  return state.map((trainer) =>
    trainer.id === payload.id
      ? { ...trainer, selected: true } 
      : trainer.selected
        ? { ...trainer, selected: false }
        : trainer
    );

或更多干燥

case "SELECT_TRAINER":
  return state.map((trainer) =>
    trainer.id === payload.id || trainer.selected
      ? { ...trainer, selected: trainer.id === payload.id } 
      : trainer
    );

您需要派遣培训师 id 进行操作。为此,我建议将 redux 逻辑从 Select 组件移动到 Trainer 组件,以便它计算选定的训练器值并直接使用当前训练器的 id 调度 selectedTrainer 操作。

function Trainer(props) {
  const dispatch = useDispatch();
  const allTrainers = useSelector((state) => state.trainers);
  const isSelected = allTrainers.some(trainer => trainer.selected);

  return (
    <button onClick={() => dispatch(actions.selectTrainer(props.id))}>
      {isSelected ? "Selected" : "Select"}
    </button>
  );
}

为了避免浅拷贝训练者数组,将选定的训练者 ID 存储为单独的状态块可能更有意义。

示例:

const initialState = {
  trainers: [
    {
      id: uuid(),
      name: '',
      team: [],
    }
  ],
  selected: null
};

const trainerReducer = (state = initialState, action) => {
  const {type, payload} = action
  
  switch(type) { 
    case "SELECT_TRAINER":
      return {
        ...state,
        selected: state.selected === payload.id ? null : payload.id
      }

    ... other cases...

    default:
      return state;
  }
};

...

function Trainer(props) {
  const dispatch = useDispatch();
  const selected = useSelector((state) => state.trainers.selected);

  return (
    <button onClick={() => dispatch(actions.selectTrainer(props.id))}>
      {selected === props.id ? "Selected" : "Select"}
    </button>
  );
}