首页 > 解决方案 > Redux 触发的函数未注册组件当前状态

问题描述

TL;博士

当存储更改触发组件功能时,当前组件状态将被忽略/重置,不允许我使用其状态数据来提供触发功能。

详细描述

这个 react-native 应用程序有一个位于标题 Appbar 堆栈导航器中的按钮,它必须触发当前聚焦的 Screen 具有的功能。问题是这个屏幕在导航方案中非常深入,因此我决定使用 Redux 直接通知屏幕按钮已被按下。这也意味着每次按下此按钮并调度存储切片时,我只能根据 Screen 实现触发任何功能。

如果我从组件中的按钮使用完全相同的功能,它会完美运行。但是,如果我从 redux 存储更改中调用相同的函数,我会得到这个日志:

控制台行为

# component loaded
false

# started writing, this is the component state
h
he
hel 
hell
hello 

#header button 'create' state change detected
true

#content as viewed by the onPressPublish function
content: ""

Error 400 - Cannot save empty content

#store reset for further use
false

应用栏


export const AppBarStackNavigator = (props) => {
    const { toggle } = useSelector(toolbarSelector);
    const handleCreatePress = () => {
        dispatch(setCreate({ pressed: true }));
    }
return (
        <Appbar.Header
            style={{ backgroundColor: theme.colors.background, elevation: 0 }}
        >
                         <Button
                            icon="seed"
                            mode="contained"
                            // disabled={!contentProps.valid}
                            onPress={handleCreatePress}
                            labelStyle={{ color: 'white' }}
                            style={{
                                width: 115,
                                borderRadius: 50,
                                alignSelf: "flex-end"
                            }}>
                            Sembrar
                        </Button>
        </Appbar.Header>
    );
}

店铺

import { createSlice } from "@reduxjs/toolkit";

export const toolbarSlice = createSlice({
    name: 'toolbar',
    initialState: {
        create: false
    },
    reducers: {
        setCreate(state, action) {
            state.create = action.payload.pressed; 
        }
    }
})

export const { setCreate } = toolbarSlice.actions;

export const toolbarSelector = state => state.toolbar

export default toolbarSlice.reducer;

导航深度组件

import { toolbarSelector, setCreate } from '../store/toolbar';
import { useSelector } from 'react-redux';
// import { useFocusEffect, TabActions, useNavigation } from '@react-navigation/native';

export const DeepComponent = (props) => {
    const theme = useTheme();
    const { create } = useSelector(toolbarSelector);

    return (
        <ChildComponent {...props} create={create} setCreate={setCreate} style={{ backgroundColor: theme.colors.background }} />
    );
};

它的孩子(函数在哪里)

import { useDispatch, useSelector } from 'react-redux';

export const ChildComponent = (props) => {
    const dispatch = useDispatch();
    const [content, setContent] = useState(''));

    let payload = {};

    const onPressPublish = async () => {
        try {
            console.log(payload);
            payload = {
                ...payload,
                content,
                // images <- other component states
            }
            console.log(payload);
            const seed = await api.writeOne(payload);
        } catch (error) {
            console.log(error);
            Alert.alert('Could not publish :(', error.message);
        }
        navigation.goBack();
    }

    useEffect(() => {
        console.log(props.create)
        console.log(content)
        if (props.create) {
            console.log(content)
            onPressPublish();
        }
        return () => {
            dispatch(props.setCreate({ pressed: false }));
        };
    }, [props.create])

    const onTextChange = (value, props) => {
        // ...
        setContent(value);
        // ...
    }

return (
        <TextInput 
            mode='flat'
            placeholder={inputPlaceholder}
            multiline
            onChangeText={text => onTextChange(text, props)}
            keyboardShouldPersistTaps={true}
            autoFocus
            clearButtonMode='while-editing'>
            <ParsedContent content={content} />
        </TextInput>
        <Button            
            disabled={!contentProps.valid}
            onPress={onPressPublish}>
            {buttonText}
        </Button>
    )
}

标签: javascriptreact-nativereduxreact-state-management

解决方案


以下是更改代码的一些建议,您仍然没有在您的问题中提供任何有意义的代码(例如有效负载变量),但这可能会让您知道去哪里。

当您使用 create-react-app 创建应用程序时,您应该有一个 linter 来告诉您何时缺少挂钩中的依赖项,您不应忽略这些警告:

//create onPressPublish when component mounts
const onPressPublish = useCallback(async (content) => {
  try {
    //removed payload as it makes no sense to create it
    //  and never use it anywhere
    //removed assigning to seed becasue it is never used anywhere
    await api.writeOne({ content });
  } catch (error) {
    console.log(error);
    Alert.alert('Could not publish :(', error.message);
  }
  navigation.goBack();
}, []);
const { create, setCreate } = props;
useEffect(() => {
  if (create) {
    //passing content
    onPressPublish(content);
  }
  return () => {
    dispatch(setCreate({ pressed: false }));
  };
}, [
  //correct dependencies without linter warnings
  content,
  dispatch,
  onPressPublish,
  create,
  setCreate,
]);

推荐阅读