React Native:在上下文之间共享状态和api调用响应

时间:2019-12-04 20:25:29

标签: javascript reactjs react-native react-hooks

在一个上下文中与另一个上下文共享调用结果时,正确的结构安排是什么?

假设我有两个问题:一个处理与QR码相关的所有内容(相机权限,扫描等),另一处理与学生相关的所有内容(列表,api调用等)

QrContext:

import React from 'react';
import createDataContext from './createDataContext';

const qrReducer = (state, action) => {
    switch (action.type) {
        case 'start':
            return {...state, cameraOpen: true, code: null, scanned: false };
        case 'end': {
            return {...state, cameraOpen: false, code: null };
        }
        case 'scan': {
            return {...state, code: action.payload, scanned: true };
        }
        default:
            return state;
    }
};
const startCamera = dispatch => () => {
  dispatch({ type: 'start' });
};

const stopCamera = dispatch => () => {
  dispatch({ type: 'end' });
};

const scan = dispatch => ( data ) => {
    dispatch({ type: 'scan', payload: data });
};

export const { Provider, Context } = createDataContext(
    qrReducer,
    { startCamera, stopCamera, scan },
    { cameraOpen: false, code: null, scanned: false }
);

StudentsContext:

import createDataContext from './createDataContext';

const studentsReducer = (state, action) => {
    switch (action.type) {
        case 'student':
            return {...state, students: [...state.students, action.payload]};
        default:
            return state;
    }
};

const findStudentQR = dispatch => async (qr) => {
    const res = await API.get('/student', {
        params: {
            id: qr
        }
    });
    if(res.data && res.data._id) {
//...
    } else {
//...
    }
    dispatch({ type: 'student', payload: res.data});

};

export const { Provider, Context } = createDataContext(
    studentsReducer,
    { findStudentQR },
    { students: [] }
);

然后在它们之间共享状态,这是一个钩子: useStudentQR:

import { useContext } from 'react';
import { Context as QrContext } from '../context/QrContext';
import { Context as StudentsContext } from '../context/StudentsContext';
import { navigate } from "../navigationRef";

export default () => {
    const { state: { code }, stopCamera } = useContext(QrContext);
    const { state: {students}, findStudentQR } = useContext(StudentsContext);
    const readStudent =  async () => {
        const student =  await findStudentQR(code);
        stopCamera();
        navigate('Student');
    };
    return [readStudent];
}

然后是我的ScanScreen:

import React, { useContext } from 'react'
import { View, Text, StyleSheet, SafeAreaView, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
import { NavigationEvents } from 'react-navigation';
import { Context as QrContext } from '../context/QrContext';
import useQR from '../hooks/useQR';
import useStudentQR from '../hooks/useStudentQR';

const ScanScreen = () => {
    const { state: { scanned }, startCamera, stopCamera, scan } = useContext(QrContext);
    const [err] = useQR(true); // asks for camera permission
    const [readStudent] = useStudentQR();

    return <SafeAreaView forceInset={{ top: "always" }} style={styles.view}>
        <NavigationEvents onWillFocus={startCamera} />
        <BarCodeScanner
            onBarCodeScanned={scanned ? undefined : readStudent}
            style={styles.camera}
        />
    </SafeAreaView>
};

const styles = StyleSheet.create({
    ...
});

export default ScanScreen

所以我当前的问题是在useStudentQr内部,它没有扫描功能的更新结果。

我相信这是因为当我在useStudentQr内调用ScanScreen时,当时的状态已将code设置为null。当我调用readStudent()时,它仍在使用useStudentQr的旧实例。

处理上下文之间逻辑的正确方法是什么?是否打算在表格中完成?

0 个答案:

没有答案