请问React(或者zustand)中是否可以对已经存在的状态做监听生成一个新的状态?

使用的是zustand的三方状态库,
有一个场景:store中有一个数组 bearList,我想要在bearList的元素数量为1的时候,触发事件。
是否可以用一个新的状态名来进行代替bearList的数量是否为1呢?比如:bearCountOne: boolean。

在vue中好像有watch的组件属性可以实现这样的功能,但是在react中是否有类似的方式呢?

阅读 1.3k
2 个回答

使用 useStore 来管理 bearList 和bearCountOne 的状态,并在 addBear 和 removeBear 方法中更新 bearCountOne 的值。然后在 ExampleComponent 中使用 React.useEffect 来监听bearCountOne 的变化,并在其值为 true 时触发事件。

import create from 'zustand';

const useStore = create((set) => ({
  bearList: [],
  bearCountOne: false,
  error: null,
  addBear: (bear) => set((state) => {
    try {
      const newBearList = [...state.bearList, bear];
      return {
        bearList: newBearList,
        bearCountOne: newBearList.length === 1,
        error: null,
      };
    } catch (error) {
      return { error: 'Failed to add bear' };
    }
  }),
  removeBear: (bear) => set((state) => {
    try {
      const newBearList = state.bearList.filter((b) => b !== bear);
      return {
        bearList: newBearList,
        bearCountOne: newBearList.length === 1,
        error: null,
      };
    } catch (error) {
      return { error: 'Failed to remove bear' };
    }
  }),
}));

// 使用示例
const ExampleComponent = () => {
  const { bearList, bearCountOne, addBear, removeBear, error } = useStore();

  React.useEffect(() => {
    if (bearCountOne) {
      // 触发事件
      console.log('Bear count is one!');
    }
  }, [bearCountOne]);

  return (
    <div>
      <button onClick={() => addBear('Bear')}>Add Bear</button>
      <button onClick={() => removeBear('Bear')}>Remove Bear</button>
      <div>Bear List: {bearList.join(', ')}</div>
      <div>Bear Count One: {bearCountOne.toString()}</div>
      {error && <div style={{ color: 'red' }}>{error}</div>}
    </div>
  );
};

推荐1和3,简单的store里直接派生就可以,复杂一些的再用selector更好
store里直接派生:

import create from 'zustand'

const useStore = create((set, get) => ({
  bearList: [],
  bearCountOne: false,
  
  addBear: (bear) => {
    set((state) => ({
      bearList: [...state.bearList, bear],
      bearCountOne: [...state.bearList, bear].length === 1
    }))
  },
  
  removeBear: (id) => {
    set((state) => ({
      bearList: state.bearList.filter(b => b.id !== id),
      bearCountOne: state.bearList.filter(b => b.id !== id).length === 1
    }))
  }
}))

用useEffect:

function BearComponent() {
  const bearList = useStore((state) => state.bearList)
  const setBearCountOne = useStore((state) => state.setBearCountOne)
  
  useEffect(() => {
    setBearCountOne(bearList.length === 1)
  }, [bearList, setBearCountOne])
  
  return (...)
}

用zustand的selector:

import create from 'zustand'

const useStore = create((set, get) => ({
  bearList: [],
  
  getBearCountOne: () => get().bearList.length === 1,
  
  addBear: (bear) => set((state) => ({ 
    bearList: [...state.bearList, bear] 
  })),
  
  removeBear: (id) => set((state) => ({ 
    bearList: state.bearList.filter(b => b.id !== id) 
  }))
}))

// 在组件里用
function Component() {
  const bearCountOne = useStore((state) => state.getBearCountOne())
  // ...
}

用zustand的subscribe方法:

import create from 'zustand'

const useStore = create((set, get) => ({
  bearList: [],
  bearCountOne: false,
  
  addBear: (bear) => set((state) => ({ 
    bearList: [...state.bearList, bear] 
  })),
  
  removeBear: (id) => set((state) => ({ 
    bearList: state.bearList.filter(b => b.id !== id) 
  }))
}))

// 订阅状态变化
useStore.subscribe(
  (state) => state.bearList,
  (bearList) => {
    useStore.setState({ bearCountOne: bearList.length === 1 })
  }
)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏