Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
136 views
in Technique[技术] by (71.8m points)

reactjs - State in app doesn't change after it's function is called first time. It needs two tries to change

I have code as below. My app fetches encrypted password from API and after decrypting, copies it to clipboard for few seconds. Decrypting takes place the moment I press Copy Password button. However, when I press button 1 time my password isn't copied to clipboard which means, that for some reason state password wasn't changed. Password is copied to clipboard only after I press it 2 times in short amount of time. What could be reason behind that? I've tested case "dec_password" and decPassword quite a bit and to me it seems, actual issue happens in component, not in context.

Component:

import React, { useContext, useEffect } from "react";
import { View, StyleSheet, Text, Clipboard } from "react-native";
import { Context as PasswdDetailContext } from "../context/PasswdDetailContext";
import { Button, Input } from "react-native-elements";
import { decryptRecord } from "../components/Crypto";
import { Context as AuthContext } from "../context/AuthContext";
import { NavigationEvents } from "react-navigation";
import Spacer from "../components/Spacer";

const PasswdDetailScreen = ({ navigation }) => {
  const {
    state: { username, password, domain, description },
    decData,
    decPassword,
    resetPassword,
    reset,
  } = useContext(PasswdDetailContext);
  const {
    state: { secretKey },
  } = useContext(AuthContext);
  const id = navigation.getParam("id");

  const clipboardPasswd = () => {
    Clipboard.setString(password);
    setTimeout(() => {
      Clipboard.setString("");
      resetPassword();
    }, 10000);
  };

  return (
    <>
      <NavigationEvents
        onWillFocus={() => decData({ id, secretKey })}
        onDidBlur={() => {}}
      />
      <Text>Username: {username}</Text>
      <Text>Password: {password}</Text>
      <Text>Description: {description}</Text>
      <Button
        title="Copy Password"
        onPress={() => decPassword({ id, secretKey })}
        onPressIn={() => clipboardPasswd()}
      />
      <Input label="Password" />
    </>
  );
};

const styles = StyleSheet.create({});

export default PasswdDetailScreen;

Context:

import createDataContext from "./createDataContext";
import trackerApi from "../api/tracker";
import { AsyncStorage } from "react-native";
import { decryptRecord } from "../components/Crypto";

const passwdDetailReducer = (state, action) => {
  switch (action.type) {
    case "dec_username":
      return { ...state, username: action.payload };
    case "dec_password":
      return { ...state, password: action.payload };
    case "dec_domain":
      return { ...state, domain: action.payload };
    case "dec_description":
      return { ...state, description: action.payload };
    case "reset_password":
      return { ...state, password: "" };
    case "reset":
      return {};
    default:
      return state;
  }
};

const decData = (dispatch) => async ({ id, secretKey }) => {
  const response = await trackerApi.get("/api/password/" + id + "/");
  var responseUser = response.data.username;
  var responseDesc = response.data.description;
  var decUsername = decryptRecord(responseUser, secretKey);
  var decDescription = decryptRecord(responseDesc, secretKey);
  dispatch({ type: "dec_username", payload: decUsername });
  dispatch({ type: "dec_description", payload: decDescription });
};

const decPassword = (dispatch) => async ({ id, secretKey }) => {
  const response = await trackerApi.get("/api/password/" + id + "/");
  const responsePassword = response.data.password;
  const decPassword = decryptRecord(responsePassword, secretKey);
  dispatch({ type: "dec_password", payload: decPassword });
};

const resetPassword = (dispatch) => () => {
  dispatch({ type: "reset_password" });
};

const reset = (dispatch) => () => {
  dispatch({ type: "reset" });
};

export const { Provider, Context } = createDataContext(
  passwdDetailReducer,
  { decData, decPassword, reset, resetPassword },
  { username: "", password: "", domain: "", description: "" }
);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

you want to listen in on the changes on password, and only copy it when it's not empty. you might also want to disable the button when it's clicked.

import React, { useContext, useEffect } from "react";
import { View, StyleSheet, Text, Clipboard } from "react-native";
import { Context as PasswdDetailContext } from "../context/PasswdDetailContext";
import { Button, Input } from "react-native-elements";
import { decryptRecord } from "../components/Crypto";
import { Context as AuthContext } from "../context/AuthContext";
import { NavigationEvents } from "react-navigation";
import Spacer from "../components/Spacer";

const PasswdDetailScreen = ({ navigation }) => {
  const {
    state: { username, password, domain, description },
    decData,
    decPassword,
    resetPassword,
    reset,
  } = useContext(PasswdDetailContext);
  const {
    state: { secretKey },
  } = useContext(AuthContext);
  const id = navigation.getParam("id");

  const clipboardPasswd = () => {
    Clipboard.setString(password);
    setTimeout(() => {
      Clipboard.setString("");
      resetPassword();
    }, 10000);
  };
  useEffect(()=>{
     if (password !== '') clipboardPasswd();
  },[password]);

  return (
    <>
      <NavigationEvents
        onWillFocus={() => decData({ id, secretKey })}
        onDidBlur={() => {}}
      />
      <Text>Username: {username}</Text>
      <Text>Password: {password}</Text>
      <Text>Description: {description}</Text>
      <Button
        title="Copy Password"
        onPress={() => decPassword({ id, secretKey })}
      />
      <Input label="Password" />
    </>
  );
};

const styles = StyleSheet.create({});

export default PasswdDetailScreen;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...