Reactjs 如何修复reducer以返回对象的属性值?
我的react原生应用程序中有一个reducer,理想情况下,它应该检查状态并返回配方是否受欢迎。我已经尝试创建一个reducer来返回状态中的recipe对象的isFav是true还是false。如果未在状态中找到配方,则应返回false 我在想如何写减速机时遇到了麻烦。这就是我目前所拥有的 这是我的最爱Reactjs 如何修复reducer以返回对象的属性值?,reactjs,react-native,redux,redux-reducers,Reactjs,React Native,Redux,Redux Reducers,我的react原生应用程序中有一个reducer,理想情况下,它应该检查状态并返回配方是否受欢迎。我已经尝试创建一个reducer来返回状态中的recipe对象的isFav是true还是false。如果未在状态中找到配方,则应返回false 我在想如何写减速机时遇到了麻烦。这就是我目前所拥有的 这是我的最爱 import { TOGGLE, IS_FAVOURITE } from '../actions' export const favids = (state = [], action) =
import { TOGGLE, IS_FAVOURITE } from '../actions'
export const favids = (state = [], action) => {
const { type, recipeid } = action
const newRecipe = {
recipeid,
is_fav: true,
}
switch (type) {
case TOGGLE: {
// console.log(`Toggle State = ${JSON.stringify(state)}`)
// console.log(`Toggle recipe id : ${recipeid}`)
return state.findIndex(recipe => recipe.recipeid === recipeid) === -1 ?
[...state, newRecipe] :
state.map(recipe =>
recipe.recipeid === recipeid ?
{ ...recipe, is_fav: !recipe.is_fav } : recipe
)
}
case IS_FAVOURITE: {
//console.log(`Is Favourite state =${JSON.stringify(state)}`)
return state.map(recipe =>
recipe.recipeid === recipeid ?
recipe.is_fav : state
)
}
default:
return state
}
}
这是我的actions.js
export const TOGGLE = 'TOGGLE'
export const toggleFavId = id => ({
type: 'TOGGLE',
recipeid: id
})
export const IS_FAVOURITE = 'IS_FAVOURITE'
export const isFavourite = id => (
{
type: 'IS_FAVOURITE',
recipeid: id
}
)
我试图修改is_favorite reducer以返回true或false,这是保存在状态中的配方对象的is_fav属性的值
在渲染组件时,我尝试在可见组件的useEffect中调用此函数
这是favicon.js文件
import React, {useState, useEffect} from 'react'
import { FontAwesome } from '@expo/vector-icons'
import { View, TouchableOpacity,StyleSheet, Text, Alert } from 'react-native'
const FavIcon = ({recipeid, onToggle, isFavourite, text}) => {
const [isFavNew, setFavNew] = useState(false)
const toggleFav = (recipeid) =>{
setFavNew(!isFavNew)
onToggle(recipeid)
}
useEffect(() => {
console.log("Entered useEffect")
console.log(`Recipeid = ${recipeid}`)
console.log(`Favicon UseEffect IS Favourtie Recipe id:> ${JSON.stringify(isFavourite(recipeid))}`)
**// if (recipeid > 0)
// setFavNew((isFavourite(recipeid))
// else {
// setFavNew(false)
// }**
},[])
// console.log(`Is Favourite in Favicon is = ${isFavourite(recipeid)}`)
return (
<View>
<TouchableOpacity style={styles.favItem} onPress={() => toggleFav(recipeid)}>
<FontAwesome name={isFavNew === true ? 'heart' : 'heart-o'} size={40} color='red' />
<Text> {text}</Text>
</TouchableOpacity>
</View>
)
}
export default FavIcon
import React,{useState,useffect}来自“React”
从“@expo/vector icons”导入{FontAwesome}
从“react native”导入{View、TouchableOpacity、样式表、文本、警报}
const FavIcon=({recipeid,onToggle,isFavorite,text})=>{
const[isFavNew,setFavNew]=useState(false)
const toggleFav=(recipeid)=>{
setFavNew(!isFavNew)
onToggle(recipeid)
}
useffect(()=>{
console.log(“输入useffect”)
log(`Recipeid=${Recipeid}`)
log(`Favicon useffect IS favorite Recipe id:>${JSON.stringify(isfavorite(recipeid))}`)
**//如果(recipeid>0)
//setFavNew((isfavorite(recipeid))
//否则{
//setFavNew(假)
// }**
},[])
//log(`Is Favicon中的收藏夹Is=${IsFavorite(recipeid)}`)
返回(
切换FAV(recipeid)}>
{text}
)
}
导出默认FavIcon
如果我正确理解您的问题,那是因为对Redux的误解。您正在寻找一个选择器,而不是由reducer处理的操作
Redux不过是一个大而奇特的对象。还原器修改对象的属性。操作告诉还原器如何做。选择器将这些属性返回给您
您可以在减速器中删除具有相同名称的切换动作和大小写。然后创建一个选择器,如下所示:
const isRecipeFavorited=(recipeId)=>(状态)=>{
const recipe=state.find(recipe=>recipe.id==recipeId;
返回配方?配方.is_fav:false;
};
选择器是一个将整个状态作为参数并返回子集的函数。当您使用useSelector
时,Redux会为您传递整个状态。因此,像这样的函数就是“选择器工厂”,其中您将使用配方ID调用它,它将返回该配方的选择器。您将如下使用它:
从'react redux'导入{useSelector};
从{selectors path}导入{isRecipeFavorited};
...
常量RecipeFavorited=useSelector(isRecipeFavorited(recipeId));
另一方面,如果您最终获得大量状态信息,您可以进行一些优化。最重要的是将您的配方存储在一个对象中,而不是存储在一个数组中。我假设您从API获得了一个配方数组。假设您可以依靠唯一的配方ID,您可以迭代粗略绘制阵列并将每个阵列存储在一个对象中:
const recipesState = {};
returnedRecipes.forEach(recipe => {
recipesState[recipe.id] = recipe;
};
然后,当您在还原器中选择配方时,您不必遍历整个列表以获得所需的配方或存储结果。您可以在O(1)时间内完成这些操作,因为您已经知道配方ID
然后,您的是您最喜欢的减速器壳,可能看起来像:
大小写切换:{
const tempRecipes={…state};
const currentRecipe=tempRecipes[recipeId];
当前配方
?currentRecipe.is_fav=!currentRecipe.is_fav
:tempRecipes[recipeId]=新配方;
返回菜谱;
}
然后,您可以像这样设计我上面描述的选择器:
const isRecipeFavorited=(recipeId)=>({recipe})=>recipe[recipeId]
?配方[recipeId]。是否为fav
:假;
非常感谢您,我一直在努力解决这个问题。我尝试更新您提到的代码,但我一直收到一个错误,说_selectors.isRecipeFavorited不是一个函数。我还尝试使用useEffect修复它,但没有修复错误。从“../selectors/selectors”导入{isRecipeFavorited}{useSelector}来自'react redux'const FavIcon=({recipeid,onToggle,IsFavorite,text})=>{const[isFavRecipe,setIsFavRecipe]=useState(false)useEffect((recipeid)=>{SetIsFavRecipeId(useSelector(isRecipeFavorited,recipeid))},[])const isFavNew=useSelector(isRecipeFavorited(recipeid))
我制作了一个代码笔来展示我对此的建议。不要将IsFavorite属性存储在本地状态中——尽可能依赖状态的Redux。这消除了对useEffect的需要,也不需要调用挂钩(如useSelector)除了函数组件的根目录之外的任何位置。我在这里重新提交了这个问题,并提供了有关代码的更多信息。我仍然收到错误消息,即_selectors.isRecipeFavorited不是函数。