Reputation: 113
Context
I've created a custom React Native Text component that I call TextInputSetting
, which should update the redux state as a user enters text into it.
The component works fine if I use it just once, but as soon as I try to reuse it, I run into problems (see GIF below to see what I mean).
In experimenting, I found that if I duplicate the component definition (i.e. create TextInputSetting2
), I run into the same problem. However, if I duplicate the component and use different variables names for the results of the call to useState
(i.e. tempText2
& setTempText2
in one component definition and tempText
& setTempText
in the other), only then the component instances will function as expected.
Question
Why can't I invoke useState
in a reusable React Native + Redux component, and have it work as expected?
Details
TextInputSetting.js
import React, { useState } from "react";
import { Text, TextInput, View } from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { updateSetting } from "./actions";
export const TextInputSetting = (props) => {
const settings = useSelector((state) => state.settingsReducer);
const dispatch = useDispatch();
[tempText, setTempText] = useState(settings[props.settingKey]);
return (
<View style={[{ paddingLeft: 50, marginTop: 5, flexDirection: "row" }]}>
<Text>{props.label}:</Text>
<TextInput
value={tempText}
style={{
backgroundColor: "yellow",
borderWidth: 1,
width: props.boxWidth,
textAlign: "center",
}}
onChangeText={(text) => setTempText(text)}
onEndEditing={() => dispatch(updateSetting(props.settingKey, tempText))}
/>
</View>
);
};
actions.js
export const UPDATE_STATE = "UPDATE_STATE";
export const updateSetting = (k, v) => (dispatch) => {
dispatch({
type: UPDATE_STATE,
payload: { key: k, value: v },
});
};
reducers.js
import { UPDATE_STATE } from "./actions";
const defaultSettings = {
set1: "default1",
set2: "default2",
};
export const settingsReducer = (state = defaultSettings, action) => {
switch (action.type) {
case UPDATE_STATE:
return { ...state, [action.payload.key]: action.payload.value };
default:
return state;
}
};
App.js
import React from "react";
import { Text } from "react-native";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { persistor, store } from "./store";
import { TextInputSetting } from "./TextInputSetting";
export default function App() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<>
<Text style={{ fontSize: 50, textAlign: "center", paddingTop: 200 }}>
Hi there
</Text>
<TextInputSetting
label="First Field"
settingKey="set1"
boxWidth={200}
/>
<TextInputSetting
label="Second Field"
settingKey="set2"
boxWidth={200}
/>
</>
</PersistGate>
</Provider>
);
}
Code
You can run the code for yourself; I've zipped the full example here (less than 1 MB): https://drive.google.com/file/d/1FJ5AGXlT680uvHIjKxaZUEwliW79_MmT/view?usp=sharing
Upvotes: 1
Views: 55
Reputation: 11915
The issue is on this line.
[tempText, setTempText] = useState(settings[props.settingKey]);
It should be
const [tempText, setTempText] = useState(settings[props.settingKey]);
Upvotes: 1