Реагировать на родной - есть ли способ использовать объект с другой страницы? - PullRequest
1 голос
/ 11 февраля 2020

Я хочу знать, как я могу использовать "userPrincipalName" на других страницах. Что мне нужно сделать, чтобы это работало? в моем примере я пытаюсь использовать объект «userPrincipalName» на MainScreenpage , но я не понимаю, как это сделать.

это мой пример модальной страницы который имеет объект "userPrincipalName":

import React,
{ Component } from 'react';
import {
  Text,
  TouchableOpacity,
  StyleSheet,
  View,
} from 'react-native';
import Modal from 'react-native-modal';
import PlacesNavigator from '../navigation/PlacesNavigator';
import { LinearGradient } from 'expo-linear-gradient';
import { AzureInstance, AzureLoginView } from 'react-native-azure-ad-2';

const credentials = {
  client_id: 'ea00ca9e-8c37-4520-8d80-2c2bb9239bf8',
  scope: 'User.Read',
};

export default class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      visibleModal: 3,
      azureLoginObject: {},
      loginSuccess: false
    };
    this.azureInstance = new AzureInstance(credentials);
    this._onLoginSuccess = this._onLoginSuccess.bind(this);
  }

  _renderButton = () => (
    <TouchableOpacity
      onPress={() => this.setState({ visibleModal: false })}>
      <LinearGradient
        colors={['#4c669f', '#3b5998', '#192f6a']}
        style={{
          height: 80,
          width: 180,
          borderRadius: 10,
          backgroundColor: "#2196F3",
          justifyContent: 'center',
          alignItems: 'center',
          marginTop: 50,
        }}>
        <Text style={{ color: 'white', fontSize: 20, fontWeight: 'bold' }}>כניסה</Text>
      </LinearGradient>
    </TouchableOpacity>

  );

  _onLoginSuccess() {
    this.azureInstance.getUserInfo().then(result => {
      this.setState({
        loginSuccess: true,
        azureLoginObject: result,
      });
      console.log(result);
    }).catch(err => {
      console.log(err);
    })
  }

     renderWelcomeMsg = (currentTime = new Date()) => {
    const currentHour = currentTime.getHours()
    const splitAfternoon = 12;
    const splitEvening = 17; 
    if (currentHour >= splitAfternoon && currentHour <= splitEvening) {
      return 'צהריים טובים,';
    } else if (currentHour >= splitEvening) {
      return 'ערב טוב,';
    }
    return 'בוקר טוב,';
  }

  render() {
    if (!this.state.loginSuccess) {

      return (
        <AzureLoginView
          azureInstance={this.azureInstance}
          onSuccess={this._onLoginSuccess}
        />)
    }

    if (this.state.visibleModal === 3) {
      const { givenName } = this.state.azureLoginObject;
      const { userPrincipalName } = this.state.azureLoginObject;////THIS IS THE OBJECT I WANT
      return (
        <View style={styles.container}>
          <Modal
            isVisible={this.state.visibleModal === 3}
            animationInTiming={1000}
            animationOutTiming={1000}
            backdropTransitionInTiming={4000}
            backdropTransitionOutTiming={4000}
            animationIn={'flipInY'}
          >
            <LinearGradient
              colors={['#43D4FF', 'white']}
              style={{ borderRadius: 10 }}>
              <View style={styles.modalContent}>
                <Text style={{
                  fontWeight: "bold",
                  fontSize: 35,
                  justifyContent: 'center',
                  alignItems: 'center',    
                }}>{this.renderWelcomeMsg()} {givenName}
                </Text>
                <View style={styles.buttonContainer}>
                  {this._renderButton()}
                </View>
              </View>
            </LinearGradient>
          </Modal>
        </View>


      );
    }
    return (
      <PlacesNavigator />
    );
  }
}

И это MainScreen страница , которую я хочу использовать объект "userPrincipalName" в Ax ios:

import React, { Component } from "react";
import {
    View,
    Text,
    StyleSheet,
    ActivityIndicator,
    Platform,
    FlatList,
    TouchableOpacity,
    TouchableHighlight,
    WebView
} from "react-native";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/HeaderButton";
import axios from "axios";
import moment from 'moment'
import storeService from '../components/storeService'



export default class MainScreen extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],
            userPrincipalName: null
        };
    }

    getData = () => {
        this.setState({ isLoading: true, data: [] })
        axios.get("https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApp_Get_Orders_To_Approve/" + userPrincipalName.split('@')[0])
            .then(res => {
                this.setState({
                    isLoading: false,
                    data: res.data
                });
                console.log(res.data);
            });
    }

    componentDidMount() {
        this.props.navigation.setParams({ getData: this.getData });
        // now we load the data we stored in the async storage
        storeService.loadKey('userPrincipalName').then((res) => {
            console.log("THIS IS THE userPrincipalName", res) //res will contain the value given the key, store this value in your state and use it any where in the component
        })
        this.getData()

        // this.postData()
    }

    renderItems = (item, index) => {
        const { merhavid, yaamID, ezorID, shemEzor } = item;
        return (
            <TouchableHighlight style={{
                backgroundColor: '#ffff78'
            }}>
                <TouchableOpacity
                    style={{
                        paddingVertical: 15,
                        paddingHorizontal: 10,
                        flexDirection: "row",
                        justifyContent: "space-between",
                        alignItems: "center",
                        borderWidth: 0.8,
                        borderColor: '#d5d7db',
                        backgroundColor: index % 2 == 0 ? '#d1f0da' : '#f2f5f3',
                    }}
                    onPress={() => this.props.navigation.navigate("Info")}>
                    <Text style={styles.name}>
                        {ezorID + "" + "      |" + "               " + merhavid + " " + yaamID + " " + shemEzor}
                    </Text>
                </TouchableOpacity>
            </TouchableHighlight>
        );
    }


    render() {
        if (this.state.isLoading) {
            return (
                <View style={{ flex: 0, paddingTop: 300 }}>
                    <Text style={{ alignSelf: "center", fontWeight: "bold", fontSize: 20 }}>טוען נתונים...</Text>
                    <ActivityIndicator size={'large'} color={'#08cbfc'} />
                </View>
            );
        }
        return (
            <>
                <View style={styles.container}>
                    <FlatList
                        data={this.state.data}
                        keyExtractor={(_, index) => String(index)}
                        renderItem={({ item, index }) => { return this.renderItems(item, index) }}

                    />
                </View>

                <View style={styles.bottomMainContainer}>
                    <View style={styles.bottomView} >
                        <Text style={styles.bottomTextStyle}>סה"כ: {this.state.data.length} רשומות</Text>
                    </View>
                </View>
            </>
        );
    }
}

Ответы [ 2 ]

0 голосов
/ 11 февраля 2020

Это то, для чего React Context был разработан для:

Context обеспечивает способ передачи данных через дерево компонентов без необходимости вручную пропускать подпорки на каждом уровне.

Это также относится к обновлению данных из вложенных компонентов, например

const UserContext = React.createContext({
  user: null,
  setUser: () => {}
});

function UserContextProvider {
  const [user, setUser] = useState(null);

  return (
    <UserContext.Provider value={{ user, setUser }}>
      {props.children}
    </UserContext.Provider>
  )
}

function App() {
  return (
    <UserContextProvider>
      <MainScreen />
    </UserContextProvider>
  );
}

class MainScreen extends Component { 
  static contextType = UserContext;

  getData() {
    // We should see the user details 
     console.log(this.context.user);
  }

  render() {
    return (
      <div>
        <Example />
      </div>
    )
  }
}

class Example extends Component {
  static contextType = UserContext

  _onLoginSuccess() {
    this.azureInstance.getUserInfo().then(result => {
      this.setState(...);
      // set user in UserContext

      this.context.setUser(result);
    });
  }
}
0 голосов
/ 11 февраля 2020

Лучшим способом было бы использовать избыточное хранилище, которое поможет вам создать неизменяемый объект данных, который можно обновлять только на основе действий пользователя https://redux.js.org/basics/store/.

Другой простой, но неэффективный способ - для использования собственного асинхронного c хранилища реагирования, где вы сохраняете объект, а затем загружаете его в componentDidMount() вашего нового компонента.

Другой способ - передать эти реквизиты как ScreenProps в вашем дочернем компоненте. (это возможно только в том случае, если экраны имеют родительское дочернее отношение)


решение - разделение объекта между компонентами с использованием asn c storage

import AsyncStorage from '@react-native-community/async-storage';

const storeService = {
    async saveItem(key, value) {
        try {
            await AsyncStorage.setItem(key, value);
        } catch (error) {
            console.log('AsyncStorage Error: ' + error.message);
        }
    },

    loadKey(key) {
        return new Promise((resolve, reject) => {
            AsyncStorage.getItem(key)
                .then(res => {
                    resolve(res)
                })
                .catch(err => reject(err));
        });
    }
};

export default storeService;

Обратите внимание, что эти компоненты без состояния имеет 2 метода, один для сохранения ключа и другой для загрузки. Теперь, чтобы сохранить значение для ключа, используйте

import React,
{ Component } from 'react';

....


export default class Example extends Component {
  constructor(props) {
    super(props);
    ....
  }

  ....

  render() {

    ...

    if (this.state.visibleModal === 3) {
      const { givenName } = this.state.azureLoginObject;
      const { userPrincipalName } = this.state.azureLoginObject;

      //this is how we will store the value when this component Example loads
      storeService.saveItem('userPrincipalName', userPrincipalName)

      return (

        ....

      );
    }
    return (
      <PlacesNavigator />
    );
  }
}

И чтобы загрузить этот элемент снова, используйте

import React, { Component } from "react";

...


export default class MainScreen extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            userPricipalName: null //initialize this state variable
            data: [] 
        };
    }

    getData = () => {
        ...
        var userPrincipalName = this.state.userPrincipalName;
        axios.get("https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApp_Get_Orders_To_Approve/"+userPrincipalName.split('@')[0])

        ....
    }

    componentDidMount() {
        // now we load the data we stored in the async storage
        storeService.loadKey('userPrincipalName').then((res) => {
            this.setState({userPricipalName: res}) //store like this
        })
        this.getData()
    }

    ...


    render() {

        ....

        return (
            ....
        );
    }
}

Обратите внимание, что для того, чтобы иметь возможность сохранить весь объект в asyn c store, вам сначала нужно будет зашифровать сохраняемый объект и json разобрать при повторном чтении.

...