【问题标题】:How can I rerender my redux state after triggering an action with hooks?如何在使用钩子触发操作后重新呈现我的 redux 状态?
【发布时间】:2020-01-05 11:58:10
【问题描述】:

我正在尝试通过触发调用 API 的操作来更新 Redux 中的状态。

我已尝试使用控制台登录操作和减速器进行调试,以查看状态是否正在更改。

API 返回一个对象并将其存储到减速器中,它似乎工作正常,但屏幕 UI 没有重新渲染或更新减速器状态。

我尝试使用 useState React Hook 函数来测试问题是来自我的组件还是调度函数,结果发现问题来自 Redux 调度钩子。

在这种情况下,当我按下 ToggleSwitch 组件时,操作会触发 API 并将新值存储到 reducer。但是 UI 端的状态没有更新。

这是我的代码

减速器:

const light_list = (state: object = {}, action) => {
    if (action.type === C.FETCH_ALL_LIGHTS) {
        state = action.payload;
        return state;
    } else if (action.type === C.CHANGE_LIGHT_STATE) {
        _.merge(state[action.id].state, action.payload);
        return state;
    } else {
        return state;
    }
}

行动:

export const UpdateLightState = (lampID, jsondata) => async (dispatch, getState) => {
    const state = getState();
    const { id }: BridgePairedType = state.pairing_bridge;
    const bridge: ConfigurationTypes = state.bridge_list[id];

    const response = await axios({
        url: `http://${bridge.ipaddress}/api/${bridge.username}/lights/${lampID}/state`,
        method: 'PUT',
        data: jsondata
    });
    if (response && response.data) {
        var payload = {};
        response.data.map((data) => {
            let key = Object.keys(data.success)[0].substring(Object.keys(data.success)[0].lastIndexOf('/') + 1);
            let value = Object.values(data.success)[0];
            payload[key] = value;
        })
        dispatch({
            type: C.CHANGE_LIGHT_STATE,
            id: lampID,
            payload: payload
        })
    }
}

屏幕界面:

function ControlBulbScreen() {
    const { colors } = theme;
    const lampID = useNavigationParam('lampID');

    const dispatch = useDispatch();
    const light: LightTypes = useSelector(state => state.light_list);
    const updatelight = useCallback((lampID: string, json: LightUpdateStates) => dispatch(UpdateLightState(lampID, json)), [dispatch]);

    const bordercolor = { borderColor: colors.white }

    return (
        <Block style={styles.container}>
            <Block flex={false} center row space="between" style={styles.header}>
                <Text h1 googlebold>{light[lampID].name}</Text>
                <ToggleSwitch
                    offColor="#DDDDDD"
                    onColor={theme.colors.secondary}
                    onToggle={() => updatelight(lampID, { on: !light[lampID].state.on })}
                    isOn={light[lampID].state.on}
                />
            </Block>
        </Block>
    )
}

const styles = StyleSheet.create({
    container: {
        paddingHorizontal: theme.sizes.base * 2,
        backgroundColor: theme.colors.background 
    },
    header: {
        marginTop: 40
    },
    textControl: {
        textAlign: 'left',
        fontSize: 16
    },
    controlrow: {
        marginTop: 20,
        marginBottom: 10
    },
    thumb: {
        width: 25,
        height: 25,
        borderRadius: 25,
        borderColor: 'white',
        borderWidth: 3,
        backgroundColor: theme.colors.secondary,
    },
    textInput: {
        height: 30,
        borderBottomWidth: .5,
        borderRadius: 0,
        borderWidth: 0,
        color : theme.colors.white,
        textAlign: 'left',
        paddingBottom: 10
    }
});

export default ControlBulbScreen;

【问题讨论】:

    标签: javascript reactjs react-native redux react-hooks


    【解决方案1】:

    我想问题出在你的减速器上。你不应该直接改变你的state。我的建议是创建一个新状态,而不是您需要在每种情况下返回

    以下语句将为您完成这项工作:const newState = {...state}

    尝试以下方法:

    const light_list = (state: object = {}, action) => {
        if (action.type === C.FETCH_ALL_LIGHTS) {
            return action.payload;
        } else if (action.type === C.CHANGE_LIGHT_STATE) {
            const newState = {...state};
            _.merge(newState[action.id].state, action.payload);
            return newState;
        } else {
            return state;
        }
    }
    

    在文档中进一步了解Immutable Update Patterns

    希望对你有帮助!

    【讨论】:

    • 非常感谢您的详细解释。它现在完美运行:D
    • 建议为所有情况添加新状态还是仅用于更新/删除状态?
    • @FirmanJamal 在这些情况下,您只想更改 state。如果state 没有变化,那么拥有return state 就足够了。
    • 在状态中插入一个新对象怎么样?
    • @FirmanJamal 如果你想添加一些新的东西,那么你不应该改变原始对象。您应该复制并添加您的新对象。我希望澄清。
    猜你喜欢
    • 1970-01-01
    • 2018-10-04
    • 2017-01-24
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    • 2019-12-04
    相关资源
    最近更新 更多