简体   繁体   English

如何同时在两个不同的组件上更新相同的 redux state?

[英]How to update same redux state on two different components simultaneously?

I have a React Native scenario in which I have two components, one is a textInput and the other is a SVG drawing.我有一个 React Native 场景,其中我有两个组件,一个是textInput ,另一个是SVG绘图。 By filling out the textInput and pressing a button, the text is inserted as a data instance to an array stored in a redux state using a dispatch action (let's call it textListState ).通过填写textInput并按下按钮,文本作为数据实例插入到存储在 redux state 中的数组中,使用dispatch操作(我们称之为textListState )。

//TEXT INPUT COMPONENT
//this code is just for presentation. it will cause errors obviously
const dispatch = useDispatch();
const submitHandler = (enteredText) => {
    dispatch(submitData(enteredText))
};

return(
    <TextInput ...... />
    <TouchableOpacity onPress={() => submitHandler(enteredText) } />
)

Now, the SVG component updates all the features' fill color stored in the textListState using a function (eg setFillColor ).现在, SVG组件使用 function(例如setFillColor )更新存储在textListState中的所有特征的填充颜色。 This is done inside a useEffect hook with a dependency set to a prop (eg propA ).这是在useEffect挂钩中完成的,其依赖项设置为 prop(例如propA )。

Now the problem is that I need to add textListState as a dependency to the useEffect because I want the newly entered text from the textInput to be included in the SVG component.现在的问题是我需要添加textListState作为useEffect的依赖项,因为我希望将textInput中新输入的文本包含在SVG组件中。 But by doing so, I am creating an infinite loop, because the setFillColor also updates the textListState .但是通过这样做,我正在创建一个无限循环,因为setFillColor也会更新textListState

//SVG COMPONENT
const [textList, setTextList] = useState([]);
const textListState = useSelector(state => state.textListState);

const dispatch = useDispatch();
const setFillColor= useCallback((id, fill) => {
    dispatch(updateFillColor(id, fill))
}, [dispatch]);

useEffect(() => {
    //INFINITE LOOP BECAUSE textListState  KEEPS UPDATING WITH setFillColor
    const curTextList = [];

    for (const [i, v] of textListState.entries()) {
        setFillColor(5, "white")

        curTextList.push(
            <someSVGComponent />
        )
    }
    setTextList(curTextList);
}, [props.propA, textListState])

return(
    <G>
        {textList.map(x => x)}
    </G>
)

How can I achieve to be able to add the newly inserted text to the SVG component without creating an infinite loop?如何在不创建无限循环的情况下将新插入的文本添加到SVG组件?


EDIT:编辑:

The redux action redux 动作

export const UPDATE_TEXT = "UPDATE_TEXT";
export const SUBMIT_DATA = "SUBMIT_DATA";

export const updateFillColor = (id, fill) => {
    return { type: UPDATE_TEXT, id: id, fill: fill }
};

export const submitData= (text) => {
    return { type: SUBMIT_DATA, text: text }
};

The redux reducer redux减速机

import { TEXT } from "../../data/texts";
import { UPDATE_TEXT } from "../actions/userActions";
import { INSERT_TEXT } from "../actions/userActions";

// Initial state when app launches
const initState = {
    textListState: TEXT
};

const textReducer = (state = initState, action) => {
    switch (action.type) {
        case INSERT_TEXT :
            return {
                ...state,
                textListState: [
                    ...state.textListState,
                    action.text
                ]
            }
        case UPDATE_TEXT :
            const curText = state.textListState.filter(text => text.id === action.id)[0];

            return {
                ...state,
                textListState: [
                    ...state.textListState.slice(0, curIndex), //everything before current text
                    curText.fill = action.fill,
                    ...state.textListState.slice(curIndex + 1), //everything after current text
                ]
            }

        default:
            return state;
    }
};

export default textReducer;

if you want to trigger useEffect only when new text is added then use textListState.length instead of textListState in dependency list.如果您只想在添加新文本时触发 useEffect ,则在依赖项列表中使用textListState.length而不是textListState

If you want to do it both on update and insert (ie you want to fire even when text is updated in input) then use a boolean flag textUpdated in textListState and keep toggling it whenever there is a update or insert and use textListState.textUpdated in dependency list.如果您想在更新和插入时都执行此操作(即即使在输入中更新文本时也想触发),则在textListState中使用 boolean 标志textUpdated并在有更新或插入时继续切换它并使用textListState.textUpdated依赖列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM