【问题标题】:initialState resets after dispatch actions in react useReducer在 react useReducer 中调度操作后,initialState 重置
【发布时间】:2021-12-29 03:51:58
【问题描述】:

在我的应用程序中,我在 useEffect 挂钩内从服务器获取用户数据,并设置 useReducerinitialState。当文本输入更改发生动作调度时,initialState 重置而不是更新,因此我无法在输入中键入单词。请问有人能解决这个问题吗?我对减速器反应还很陌生。我已附上相关代码。谢谢。

EditProfile.js

const EditProfile = ({ navigation, route }) => {
  const userid = route.params.userid;
  const { user } = React.useContext(AuthContext);
  const [userData, setUserData] = React.useState(null);

  const initialState = {
    name: userData ? (userData.name ? userData.name : "") : "",
    dob: userData ? (userData.dob ? userData.dob.toDate() : "") : "",
    phone: userData ? (userData.phone ? userData.phone : "") : "",
    location: userData ? (userData.location ? userData.location : "") : "",
    caption: userData ? (userData.caption ? userData.caption : "") : "",
  };

  React.useEffect(() => {
    async function fetchData() {
      const response = await getUserData(userid);
      setUserData(response);
    }
    fetchData();
  }, []);

  const reducer = (state, action) => {
    switch (action.type) {
      case "nameInputChange":
        return {
          ...state,
          name: action.name,
        };
      case "dobInputChange":
        return {
          ...state,
          dob: action.dob,
        };
      case "phoneInputChange":
        return {
          ...state,
          phone: action.phone,
        };
      case "locationInputChange":
        return {
          ...state,
          location: action.location,
        };
      case "captionInputChange":
        return {
          ...state,
          caption: action.caption,
        };
    }
  };

  const [data, dispatch] = React.useReducer(reducer, initialState);

  const nameInputChange = (value) => {
    dispatch({
      type: "nameInputChange",
      name: value,
    });
    console.log("Name: ", initialState.name);
  };

  const dobInputChange = (date) => {
    dispatch({
      type: "dobInputChange",
      dob: date,
    });
  };

  const phoneInputChange = (value) => {
    dispatch({
      type: "phoneInputChange",
      phone: value,
    });
  };

  const locationInputChange = (value) => {
    dispatch({
      type: "locationInputChange",
      location: value,
    });
  };

  const captionInputChange = (value) => {
    dispatch({
      type: "captionInputChange",
      caption: value,
    });
  };

  return (
    <View>
      <FlatList
        showsVerticalScrollIndicator={false}
        ListHeaderComponent={() => (
          <View>
            <TouchableOpacity>
              <Image
                source={require("../assets/images/profile.jpg")}
                style={{ width: "98%", height: "98%", borderRadius: 59 }}
              />
              <View>
                <Entypo name="camera" color="#8000e3" size={18} />
              </View>
            </TouchableOpacity>
            <View>
              <VerticalNameInput
                type="name"
                label="Full Name"
                placeholder="Full name"
                color="#9798ac"
                placeholder="enter your full name"
                onChangeText={(value) => nameInputChange(value)}
                value={initialState.name}
              />
              <VerticalDateInput
                label="Date of Birth"
                color="#9798ac"
                dobInputChange={dobInputChange}
                initialState={initialState}
              />
            </View>
            <View>
              <VerticalNameInput
                type="mobile"
                label="Mobile"
                color="#9798ac"
                placeholder="mobile number"
                onChangeText={(value) => phoneInputChange(value)}
                value={initialState.phone}
              />
              <VerticalNameInput
                type="location"
                label="Location"
                color="#9798ac"
                placeholder="city and country"
                onChangeText={(value) => locationInputChange(value)}
                value={initialState.location}
              />
            </View>
            <View>
              <VerticalNameInput
                type="caption"
                label="Profile Caption"
                color="#9798ac"
                placeholder="enter about yourself"
                onChangeText={(value) => captionInputChange(value)}
                value={initialState.caption}
              />
            </View>
          </View>
        )}
      />
      <View style={{ position: "relative", top: -90, left: 200 }}>
        <FloatingAction
          onPressMain={() => {
            updateUser(userid, userData);
          }}
          floatingIcon={<Entypo name="check" size={28} color="#fff" />}
        />
      </View>
    </View>
  );
};

export default EditProfile;

VerticalNameInput.js

const VerticalNameInput = ({ label, color, placeholder, type, ...rest }) => {
  return (
    <View>
      <Text>
        {label}
      </Text>
      <View>
        <View>
          {type === "name" ? (
            <AntDesign name="user" color="#000" size={15} />
          ) : type === "mobile" ? (
            <AntDesign name="mobile1" color="#000" size={15} />
          ) : type === "location" ? (
            <EvilIcons name="location" color="#000" size={20} />
          ) : type === "caption" ? (
            <Ionicons
              name="information-circle-outline"
              color="#000"
              size={18}
            />
          ) : null}
        </View>
        <TextInput
          style={{ width: "85%", height: "100%" }}
          numberOfLines={1}
          placeholder={placeholder}
          placeholderTextColor={color}
          {...rest}
        />
      </View>
    </View>
  );
};

export default VerticalNameInput;

VerticalDateInput.js

const VerticalDateInput = ({ label, color, dobInputChange, initialState }) => {
  const [date, setDate] = React.useState(new Date());
  const [open, setOpen] = React.useState(false);

  return (
    <View>
      <Text>
        {label}
      </Text>
      <View>
        <View>
          <AntDesign name="calendar" color="#000" size={15} />
        </View>
        <View>
          <Text style={{ marginLeft: 10 }}>
            {initialState.dob
              ? initialState.dob.toDateString()
              : new Date().toDateString()}
          </Text>
          <TouchableOpacity
            style={{ marginRight: 10 }}
            onPress={() => setOpen(true)}
          >
            <AntDesign name="caretdown" color="#000" size={12} />
          </TouchableOpacity>
        </View>
        <DatePicker
          maximumDate={new Date()}
          mode="date"
          modal
          open={open}
          date={initialState.dob ? initialState.dob : date}
          onConfirm={(date) => {
            setOpen(false);
            setDate(date);
            dobInputChange(date);
          }}
          onCancel={() => {
            setOpen(false);
          }}
        />
      </View>
    </View>
  );
};

export default VerticalDateInput;

【问题讨论】:

    标签: react-native asynchronous state use-reducer actiondispatch


    【解决方案1】:

    尝试在减速器中添加“默认”情况返回当前状态。 您可能会派发一些未知的操作,而 reducer 作为结果返回 undefined。

    const reducer = (state = initialState, action) => {
      switch (action.type) {
        default:
          // If this reducer doesn't recognize the action type, or doesn't
          // care about this specific action, return the existing state unchanged
          return state
    

    } }

    【讨论】:

    • 添加默认大小写不起作用。同样的问题。
    猜你喜欢
    • 2020-10-18
    • 2017-11-09
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 2019-07-13
    • 1970-01-01
    相关资源
    最近更新 更多