How to export data from files react-native - react-native

I have a few files like Train.js and Result.js.
How can i make export voiceData from Train.js to Result.js? Files bellow:
Train.js
const Train = () => {
const [user] = useAuth()
let [started, setStarted] = useState(false);
let [results, setResults] = useState([]);
const [voiceData, setVoiceData] = useState([]);
const navigation = useNavigation()
const toResult = () => {
navigation.navigate('Result')
}
Result.js:
return (
<View style={styles.container}>
<Text>{voiceData}</Text>
<View>

Depends on how you are using it and what you want to do with it but here's an example of exporting and importing.
// Train.js
export default Train = () => {
const voiceData = "hesdsdsdsdllo";
return voiceData;
}
// App.js
import React from 'react';
import Train from './Train.js';
export function App(props) {
return (
<div className='App'>
<h1>Hello React. {Train()}</h1>
</div>
);
}
Train is a function so return what you need from it.

Related

Error Message: Invalid hook call. Hooks can only be called inside of the body of a function component

I'm trying to declare some properties using hooks, and then update using function
import React, { useState } from 'react'
const [state, setState] = useState({
drivingStatus: false,
currentWindow: 'driver'
});
export const drivingRequest = () => {
setState({...state, drivingStatus: state.drivingStatus ? false : true});
}
export const switchWindow = () => {
setState({...state, currentWindow: state.currentWindow == 'driver' ? 'user' : 'driver'});
}
Here's the error message I got:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This
could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
EDITED
This is a config file, accessible in several other files
import React, { useState } from 'react'
const [state, setState] = useState({
drivingStatus: false,
currentWindow: 'driver'
});
export const drivingRequest = () => {
setState({...state, drivingStatus: state.drivingStatus ? false : true});
}
export const switchWindow = () => {
setState({...state, currentWindow: state.currentWindow == 'driver' ? 'user' : 'driver'});
}
export const userFirstName = 'xxxx';
export const userLastName = 'xxxx';
export const userCountry = '';
export const userCountryStatus = 'active';
export const userRegion = '';
export const userIso = '';
export const userIso3 = '';
export const userLocale = 'en-US';
export const userLanguage = '';
export const userWalletBalance = 0000;
export const userNotification = 0000;
export const userAccountType = 'driver';
export const userCurrentWindow = state.currentWindow;
export const userDriverID = '';
export const userDrivingStatus = state.drivingStatus;
export const userAverageRating = (userAccountType == 'driver' && userCurrentWindow == 'driver') ? 3.9 : 2.8;
And here is a sample file where config.js is imported
import React from "react";
import { View, Text, Pressable, TouchableOpacity } from "react-native";
import { DrawerContentScrollView, DrawerItemList } from '#react-navigation/drawer';
import { useNavigation } from '#react-navigation/native';
import { userFirstName, userLastName, userAverageRating, userWalletBalance, userIso3, userNotification, userCurrentWindow, userAccountType, userDriverID, userDrivingStatus, drivingRequest, switchWindow } from './userAuth';
import Icon from 'react-native-vector-icons/MaterialIcons';
import AntDesign from 'react-native-vector-icons/AntDesign';
const CustomDrawer = (props) => {
const navigation = useNavigation();
return (
<View>
<Text>User first name: {userFirstName}</Text>
....
</View>
)
}
export default CustomDrawer;

How to get data from function component?

I have a function component (A) import another function component (B).
B has a onChange value, I want to get the onChange value all the time when I import B in A.
I have no idea how to get it.
Here is the code like this:
A:
import B from './B';
const A = () => {
// I want to get B's onChange value over here
return (
<B />
);
}
B:
import React, { useState } from 'react';
const B = () => {
const [value, setValue] = useState('');
return (
<SomePicker value={value} onChange={(value) => setValue(value)}
);
}
You can refer below solution.
import B from './B';
const A = () => {
const getOnChangeValueFromB = (data) => {
console.log(data)// you will get onChange value here
};
// I want to get B's onChange value over here
return (
<B callBack={getOnChangeValueFromB}/>
);
}
import React, { useState } from 'react';
const B = (props) => {
const [value, setValue] = useState('');
const returnValueToA = (value) => {
setValue(value)
props.callBack(value);
}
return (
<SomePicker value={value} onChange={(value) => returnValueToA(value)}
);
}

Is there a way to test code that makes API calls without mocking?

I have a FlatList that implements endless scrolling. First it fetches data from a third-party API (Marvel). Then when user scrolls to the end it fetches more. I'm having issues with a duplicate ID in the Flatlist so want to add tests to check for this. However, Jest forces you to mock API calls. Is there a way to do the test without mocking?
I'm trying to avoid an E2E test framework if possible or is that the only way?
EDIT: Code below if it's relevant:
import React, {useEffect, useRef} from 'react';
import {CText} from '#components/CText';
import {fetchComics} from '#apis/marvelApi';
import {useState} from 'react';
import {Comic, ComicsResponse} from '#src/types/marvel';
import {CActivityIndicator} from '#components/CActivityIndicator';
import {FlatList} from 'react-native-gesture-handler';
import {View} from 'react-native';
import {ActivityIndicatorType} from '#src/types';
import styles from './styles';
const renderItem = ({item, index}: {item: Comic; index: number}) => {
return <CText type="paragraph">{item.title}</CText>;
};
const keyExtractor = (item: Comic) => {
return item.id.toString();
};
/**
* https://developer.marvel.com/docs#!/public/getComicsCharacterCollection_get_2
* Will get 409 error if Limit greater than 100
*/
const ITEMS_PER_PAGE = 100;
interface Props {
characterId: number;
}
const initialState = {
offset: 0,
totalResults: -1,
};
/**
* For some reason this component doesn't unmount if you leave the screen
* by pressing the back button
*/
const ComicsComponent = (props: Props) => {
const [comics, setComics] = useState<Comic[]>(undefined);
const [isBusy, setIsBusy] = useState(true);
const [activityIndicatortype, setActivityIndicatorType] = useState<
ActivityIndicatorType
>('absolute');
const state = useRef(initialState);
const characterId = props.characterId;
/**
* This effect gets called on load and should always have offset 0
*/
useEffect(() => {
state.current = initialState;
setActivityIndicatorType('absolute');
setIsBusy(true);
setComics(undefined);
const offset = 0;
fetchComics(characterId, offset, ITEMS_PER_PAGE).then(
(response: ComicsResponse) => {
setIsBusy(false);
setComics(response.data.results);
setActivityIndicatorType('small');
state.current.totalResults = response.data.total;
},
);
return () => {
console.log('Component unmounted');
};
}, [props.characterId]);
/**
* This function gets called when the user scrolls to end of FlatList
*/
const endReachedHandler = () => {
if (
state.current.totalResults > 0 &&
state.current.offset < state.current.totalResults
) {
if (isBusy) {
return;
}
const newOffset = state.current.offset + ITEMS_PER_PAGE;
state.current.offset = newOffset;
setIsBusy(true);
fetchComics(characterId, newOffset, ITEMS_PER_PAGE).then(
(response: ComicsResponse) => {
setIsBusy(false);
if (newOffset > response.data.total) {
return;
}
//do nothing since we reached the end
else {
console.log(`Offset: ${newOffset} Comics length:${comics.length}`);
const newComics = [...comics, ...response.data.results];
setComics(newComics);
}
},
);
}
};
const content = () => {
if (comics) {
return (
<FlatList
data={comics}
renderItem={renderItem}
keyExtractor={keyExtractor}
onEndReachedThreshold={2}
onEndReached={endReachedHandler}
/>
);
} else {
return null;
}
};
return (
<View style={styles.flex}>
{content()}
{isBusy && <CActivityIndicator type={activityIndicatortype} />}
</View>
);
};
export {ComicsComponent};
It turns out you can do API calls in Jest tests in react-native by using axios package.
import 'react-native';
import axios from 'axios';
const TIMEOUT = 5000;
beforeEach(() => {});
it(
'can call Axios',
async () => {
const result = await axios.get('https://api.scryfall.com/sets');
expect(result.status).toEqual(200);
expect(result.data.object).toEqual('list');
},
TIMEOUT,
);
I had troubles doing this with the plain fetch package.

What is the best practice for unit testing my functional component with hooks in React Native?

I've written a simple wrapper component around ScrollView that enables/disables scrolling based on the available height it's given:
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {Keyboard, ScrollView} from 'react-native';
import {deviceHeight} from '../../../platform';
export default function ScrollingForm({
availableHeight = deviceHeight,
children,
}) {
const [scrollEnabled, setScrollEnabled] = useState(true);
const [formHeight, setFormHeight] = useState(0);
const scrollingForm = useRef(null);
const checkScrollViewEnabled = useCallback(() => {
setScrollEnabled(formHeight > availableHeight);
}, [availableHeight, formHeight]);
const onFormLayout = async event => {
await setFormHeight(event.nativeEvent.layout.height);
checkScrollViewEnabled();
};
useEffect(() => {
Keyboard.addListener('keyboardDidHide', checkScrollViewEnabled);
// cleanup function
return () => {
Keyboard.removeListener('keyboardDidHide', checkScrollViewEnabled);
};
}, [checkScrollViewEnabled]);
return (
<ScrollView
ref={scrollingForm}
testID="scrollingForm"
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps="handled"
scrollEnabled={scrollEnabled}
onLayout={onFormLayout}
onKeyboardDidShow={() => setScrollEnabled(true)}>
{children}
</ScrollView>
);
}
I need to write unit tests for this component. So far I have:
import React from 'react';
import {Keyboard} from 'react-native';
import {render} from 'react-native-testing-library';
import {Text} from '../..';
import ScrollingForm from './ScrollingForm';
describe('ScrollingForm', () => {
Keyboard.addListener = jest.fn();
Keyboard.removeListener = jest.fn();
let renderer;
describe('keyboard listener', () => {
it('renders text with default props', () => {
renderer = render(
<ScrollingForm>
<Text>Hello World!</Text>
</ScrollingForm>,
);
expect(Keyboard.addListener).toHaveBeenCalled();
});
it('should call listener.remove on unmount', () => {
renderer = render(
<ScrollingForm>
<Text>Goodbye World!</Text>
</ScrollingForm>,
);
renderer.unmount();
expect(Keyboard.removeListener).toHaveBeenCalled();
});
});
});
I want to also confirm that on layout if the available height is greater than the form height, that scrollEnabled is correctly being set to false. I've tried something like this:
it('sets scrollEnabled to false onFormLayout width 1000 height', () => {
mockHeight = 1000;
const {getByTestId} = render(
<ScrollingForm availableHeight={500}>
<Text>Hello World!</Text>
</ScrollingForm>,
);
const scrollingForm = getByTestId('scrollingForm');
fireEvent(scrollingForm, 'onLayout', {
nativeEvent: {layout: {height: mockHeight}},
});
expect(scrollingForm.props.scrollEnabled).toBe(false);
});

Change theme like Fabric Web ( Default / Dark)

In the documentation page of fabric, now each example component have a change theme funcionality
ie: example
enter image description here
How can I achive this funcionality. I have 2 themes (created in) and I want to switch betwen thems
Here is my preferred way, using React Context.
import React from 'react';
import { Fabric, Customizer } from '#fluentui/react';
import { useLocalStorage } from 'react-use';
// Setup Theme Context and create hooks
import {
DefaultCustomizations,
DarkCustomizations
} from '#uifabric/theme-samples';
export const ThemeList = {
light: DefaultCustomizations,
dark: DarkCustomizations
};
export const ThemeContext = React.createContext({
theme: 'light',
changeTheme: name => {}
});
const ThemeWrapper = ({ children }) => {
return (
<ThemeContext.Consumer>
{({ theme }) => (
<Customizer {...ThemeList[theme]}>
<Fabric>{children}</Fabric>
</Customizer>
)}
</ThemeContext.Consumer>
);
};
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useLocalStorage('theme', 'dark');
const changeTheme = name => ThemeList[name] && setTheme(name);
const value = { theme, changeTheme };
return (
<ThemeContext.Provider value={value}>
<ThemeWrapper>{children}</ThemeWrapper>
</ThemeContext.Provider>
);
};
export const useTheme = () => React.useContext(ThemeContext);
// Now demo how to use it
export function App() {
const { theme, changeTheme } = useTheme();
return (
<button onClick={() => changeTheme('dark')}>
Switch to dark
</button>
);
}
import ReactDOM from 'react-dom';
ReactDOM.render(
<ThemeProvider>
<App />
</ThemeProvider>,
document.getElementById('root')
);
Note to moderator: Sorry that this answer was originally a duplicate. I deleted the duplicate.