How to access props value component in test file (Jest and Enzyme) - react-native

How to access props value in component in test file (Jest and Enzyme)?
This is my component, I want to access prop value in Pin component in test file (Jest and Enzyme), is it possible?
<View style={styles.containerForm}>
<Text style={styles.textDescriptionGreyFont}>Enter Code</Text>
<Pin testID={'input_pin'} count={4} value={otp} setCode={(code) => setOtpCode(code)} />
<View style={styles.containerResendTimer}>
{renderResend()}
<Text style={styles.textDescriptionThemaFont}>{renderTimer()}</Text>
</View>
<ButtonFull
testID={'submit_otp'}
isDisabled={false}
buttonColor={fullFilled ? color.thema : color.disabledButton}
onPress={() => submitOtp()}
title={submitting ? 'Loading ...' : 'Submit'}
/>
</View>

You could find the prop value of Pin component like this
const wrapper = shallow(<Component .... />);
expect(wrapper.find(Pin).props().testID).toBe('input_pin');

I found the solution,
expect(appWrapper.find('Pin').prop('value')).toBe('')
expect(appWrapper.find('ButtonFull').prop('isDisabled')).toBe(true)

Related

Trigger event on component from another component

I am unsure how to trigger an event in my TouchableOpacity component that will target the TextInput component. I'd just like to be able to allow the user to type in a multiline area and click a button when they are finished, so that they are able to save their text (similar to how the iOS Notes app functions).
<View>
<View>
<Text>Notes</Text>
{typing &&
<TouchableOpacity
onPress={() => {
//blur() the textinput here
}}
>
<Text>Done</Text>
</TouchableOpacity>
}
</View>
<View>
<TextInput
multiline={true}
textAlignVertical='top'
value={text}
onChangeText={(text) => {
}}
onFocus={setTyping(true)}
/>
</View>
</View>
If you only need to access the text inside the same file, store your text in state in your component.
const [text, setText] = useState('');
...
<TouchableOpacity
// not sure what you want to do with the text here, but it'll be available in the `text` variable
onPress={() => saveNote(text)}
...
<TextInput
onChangeText={newText => setText(newText)
// or more simply
onChangeText={setText}
...
/>
The text input will automatically blur when you touch the Touchable.
If you need the text available in other files, have a look into React Context or look up state management libraries for React Native.

Im trying to do bottomSheet on react native but ım getting an error. Error is: Type 'string' is not assignable to type 'Ref<unknown> | undefined'

<BottomSheet
bottomSheerColor="#FFFFFF"
ref="BottomSheet"
initialPosition={'50%'}
snapPoints={['50%', '100%']}
isBackDrop={true}
isBackDropDismissByPress={true}
backDropColor="red" //======> this prop will change color of backdrop
header={
<View>
<Text style={styles.text}>Header</Text>
</View>
}
body={
<View style={styles.body}>
<Text style={styles.text}>Body</Text>
</View>
}
/>
the problem line is: ref="BottomSheet"
this ref is main problem
how can i fix this ?
String refs are legacy implementation. Please use the useRef hook to manage ref.
const bottomsheetRef = React.useRef(null)
....
<BottomSheet
ref={bottomsheetRef}
/>
Now to access the ref, do
bottomsheetRef.current

How to prevent flatlist header or footer from re-render in reactnative

I put an input field in the footer of flatlist but when i try to type anything it dismiss the keyboard automatically because of the re-render of the flatlist footer..
I tried to nest the flatlist from Scrollview but this brings warning..
How can i stop the footer from being re-rendered? can i fix this without nest the flatlist from Scrollview?
<FlatList
ListHeaderComponent={() => (
<View style={styles.discountContainer}>
<Text style={[styles.buttonText, { letterSpacing: 3 }]}>
10% DISCOUNT ON 8 COURSES
</Text>
</View>
)}
numColumns={2}
data={data}
renderItem={({ item }) => (
<View>
<SingleProduct item={item} />
</View>
)}
ListFooterComponent={() => (
<View>
<View style={styles.couponContainer}>
<Input
placeholder='Coupon code'
placeholderTextColor='#0a5796'
color='#0a5796'
inputStyle={{
color: '#0a5796',
}}
inputContainerStyle={{
borderBottomWidth: 0,
height: 50,
}}
containerStyle={styles.couponInputContainer}
onChangeText={(value) =>
this.setState({ couponCode: value })
}
value={this.state.couponCode}
/>
{couponLoading ? (
<View style={styles.couponButton}>
<ActivityIndicator />
</View>
) : (
<TouchableOpacity
style={styles.couponButton}
onPress={() => this.codeCheck(couponCode, line_items)}
>
<Text style={styles.buttonText}>Apply Coupon</Text>
</TouchableOpacity>
)}
</View>
</View>
)}
/>
Arrow-Funktions are "always" executed and create a new Reference in Memory. This way they will always re-rendering if component will be executed.
For performance reasons you better define your function outside and call it like this:
function renderMyItem(){ ...bimbom... yous stuff goes here! }
function renderHeader(){ ...bimbom... yous stuff goes here! }
<Flatlist
renderItem={this.renderMyItem()}
ListHeaderComponent={this.renderHeader()}
...
/>
What happens here?
Both of your functions renderMyItem and renderHeader will be executed once if your component is loaded and will be saved in memory. So every time you call one of the functions, you call a reference to the place in memory where they are saved.
In the other case, Arrow-Functions ()=>{...} are executed in current context and generate a new reference in Memory, each time they called, because .. to say it clear: you define & call a function that way.
If you are using Functional Component then don't use Arrow function () => (...) for header and footer components of FlatList but instead only return your header and footer Components as shown in the sample below.
<FlatList
...
ListHeaderComponent={(<View><Text>Header</Text></View>)}
ListFooterComponent={(<View><Text>Footer<Text></View>)}
/>
I was going through the same problem and the accepted answer didn't worked for me. As here the problem occurs because we are updating the state whenever the text changes (as defined in onChangeText) which causes re-rendering. Thus i came up with another solution;
First i created another dict object newState which has nothing to do with state or props. So on changing newState dict, it will not cause re-rendering. Then;
newState = {}
<TextInput onChangeText={text => this.newState.value = text} />
Then i changed the state(which is necessary as per your problem and as per mine) on onEndEditing ;
<TextInput onChangeText={text => this.newState.value = text} onEndEditing={this.setSearch} />
Here is setSearch
setSearch= () => {
this.setState({couponCode: this.newState.value})
delete this.newState.value;
}
I am deleting the key after the state is set because it doesnot update correctly next time.

useState getting confused when using multiple components

The action taken to update the state in a functional component is incorrectly updating the state of the final component loaded.
I have simplified what I'm doing to very simple code. I'm wondering if I'm missing something in why this does not work
This is parent component that loops to create subcomponents.
{scoreDays.length >0 ? scoreDays.map((el,idx) =>(
<ScoringDay key={idx} date ={el.day} score={el.score}
channels={el.channels} />
)) : null}
This is the ScoringDay component. I'm simply using a button press to update the text in state and have it displayed.
const ScoringDay = props => {
[expanded, setExpanded] = useState(false);
[test, setTest] = useState('starting text');
return(
<View>
<Text>
{test}
</Text>
<Text onPress={() =>setTest('Clicked here')}>Update value</Text>
</View>
)
In my example, 3 "ScoringDay" components are shown on the screen. However, no matter which text "Update value" I click, it always updates the text on the last component.
Why isn't the action being applied to the correct component?? I am using an index on the key...but not sure what else needs to be changed here?
Run the status change from parent to child.
[testtext, setTestText] = useState('starting text');
...
{scoreDays.length >0 ? scoreDays.map((el,idx) =>(
<ScoringDay key={idx} date ={el.day} score={el.score}
channels={el.channels} testtext={testtext} setTestText={setTestText} />
)) : null}
Used
const ScoringDay = props => {
[expanded, setExpanded] = useState(false);
const { testtext, setTestText} = props
return(
<View>
<Text>
{testtext}
</Text>
<Text onPress={() =>setTestText('Clicked here')}>Update value</Text>
</View>
)

how to navigate from nested component to other component react native?

i have a component in which on button click i render a component
<View style={styles.container}>
<Text> in Default component!</Text>
<Button title="add"
onPress={this.handelSubmit} />
{items.map((item, index) => (
<Home key={index} data={index} />))}
</View>
and my home component look like
<View style={styles.container}>
<Text onPress={() => { this.props.navigation.navigate("Calculator")}}>Semester {this.props.data +1}</Text>
</View>
onPress event i want to navigate to other screen i.e 'Calculator.js' but i got an error
i am using react-navigation for navgation
If you want to navigate from a component, you have to use your component like this:
<Home key={index} data={index} navigation={this.props.navigation} />