У меня есть сценарий React Native, в котором у меня есть два компонента, один из которых textInput
, а другой - SVG
чертеж. Заполнив textInput
и нажав кнопку, текст вставляется в качестве экземпляра данных в массив, сохраненный в состоянии избыточности, с помощью действия 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) } />
)
Теперь компонент SVG
обновляет цвет заливки всех объектов, сохраненный в textListState
, с помощью функции (например, setFillColor
). Это делается внутри useEffect
ловушки с зависимостью, установленной в проп (например, propA
).
Теперь проблема в том, что мне нужно добавить textListState
в качестве зависимости к useEffect
, потому что я хочу, чтобы вновь введенный текст из textInput
был включен в компонент SVG
. Но тем самым я создаю бесконечное l oop, потому что 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>
)
Как мне добиться того, чтобы иметь возможность добавлять вновь вставленный текст в SVG
компонент без создания бесконечного l oop?
РЕДАКТИРОВАТЬ:
Редукционное действие
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 }
};
Редуктор
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;