Whats wrong with 'react-redux.connect()' parameters? - react-native

Moving sample redux app from react to react-native.
If I pass non-empty params to react-redux 'connect' function app will crash with
on snack with message about parameter is not a function
on real device (android) about context is text and should be placed in 'Text' component
Simular code works fine on react.
On react native sample - 'connect' with empty parameters will not crash - props just will be empty
Full sample here: https://snack.expo.io/#aaronright/reduxtests

I made this change to your snack, and it seems to run fine on the ios/android simulators.
const actions = {
changeFirstName: actionChangeFirstName,
changeSecondName: actionChangeSecondName,
};
const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(actions, dispatch) });
const AppComponent = connect(
mapStateToProps,
mapDispatchToProps,
)(App);
I also added onChangeText={(text) => this.props.actions.changeSecondName(text)} to your text inputs, changing Second to First for the first name input, so that they would update state. Everything is working for me on those two simulators.
That being said, what exactly is the issue you are having? Connect requires the first param, mapStateToProps, to function, but does not require the second param, mapDispatchToProps. You can pass lodash._ for the first param if you really dont need it

Related

Why doesn't ref.current.focus() work when running tests via the #testing-library/react-native libary?

I'm attempting to write some tests for my react native app. A component in my app focuses a TextInput after a parent Pressable receives a press. I'm using a ref to identify and focus the TextInput element.
My desired functionality works just fine when running my app through expo, but my test is failing because it seems that the onFocus event is not being called.
Why isn't ref.current.focus() being called when running tests via the #testing-library/react-native library?
Here's my code:
Foo.js
import {Pressable, TextInput} from "react-native";
import {useRef} from "react";
const Foo = (props) => {
const inputRef = useRef()
return (
<Pressable testID={"pressable"} onPress={() => inputRef.current.focus()}>
<TextInput ref={inputRef} testID={"input"} onFocus={props.onFocus} />
</Pressable>
)
}
export default Foo;
Foo.test.js
import { render, screen, fireEvent } from '#testing-library/react-native';
import Foo from "./foo";
test('onFocus is called after press', () => {
const mockFocus = jest.fn();
render(<Foo onFocus={mockFocus} />)
// fireEvent(screen.getByTestId("input"), 'focus');
fireEvent.press(screen.getByTestId("pressable"));
expect(mockFocus).toHaveBeenCalled()
});
This test fails with the following message:
Error: expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
I created an issue on the RNTL GitHub page and received a response from a contributor. Copying and pasting here for easy reference for anyone who might stumble upon this thread.
This is expected as React Test Renderer which we use for rendering
does not support refs. Check #1006 for more details.
Since the behaviour of focus() triggering onFocus event would probably
involve roundtrip to native side (from JS side), then you actually
cannot test such behaviour using RNTL as we do not run native code (see
here for details).
That leaves you with following options:
Call fireEvent.focus to manually trigger onFocus on relevant
TextInput. Recommended in case focus assertion would be a part of a
step in a bigger test.
Use createNodeMock to pass ref creating function to render method, More details here. Recommended in case you
just want to assert pressing button triggers onFocus.

onWillFocus React Native v6 Replacement?

I want to clear errorMessage, when we navigate from Sign in to Sign up and vice-versa, for that I tried using onWillFocus but it has been deprecated.
Can anyone suggest me the replacement of onWillFocus?
You can use the original useEffect hook prescribed which gets triggered when a screen is loaded and when a state changes. You can either pass [] parameters so it only runs once or you can use a state to check it.
useEffect(() => {
// do you work here
}, []);

How to write to Redux store outside of a React component?

I have a React Native app where I am using HeadlessJS to call a handler on receipt of a Firebase Cloud Messaging notification.
Inside my handler which is a function, not a React component, I am accessing the Redux store using the following method:
import store from '../redux/store';
const backgroundNotificationHandler = async message => {
const state = store.getState();
...
My question is, how can I update the store in a a way that isn't a 'hack'?
Currently I have the following line in the function:
state.user.wokenFromBackgroundListener = true;
Surprisingly is works, but this is without dispatching an action or using a reducer.
Is there a better way to do it?
I can't dispatch an action because the function is not a component and it is not a component because it can't be - it requires a function as in the docs.
My code in index.js is:
AppRegistry.registerComponent(appName, () => App);
firebase.messaging().setBackgroundMessageHandler(backgroundNotificationHandler);
Dispatching from component props is just an added functionality provided by react-redux. You can still use plain redux api, in this case you can dispatch to store using store.dispatch
store.dispatch({ type: 'SOME_ACTION', payload: [1,2,3] })
However I'm not sure if you should be doing that, I haven't used HeadlessJS myself but I would first check and make sure that these task handlers are actually being run in the same context your app is running (e.g. confirm that they share store instance with your app, and NOT create a separate store just because you import store in file with the handler)

How to run code on App Start-up in React-Native

So I have a react-native application and want to run some code on app start-up;
The application has background task handlers(android) which (to the best of my knowledge) does not mount any views so initializing stuff in the root constructor or componentDidMount may not work.
I want to add certain database listeners to my application which get triggered even while the app is being run in background.
Any help on the same would be highly appreciated.
Thanks regards.
Amol.
In functional components, you want to use the useEffect() method with an empty dependency array:
useEffect(() => {
// this code will run once
}, [])
When an empty dependency array ([]) is used, the useEffect() callback is called only once, right after the component renders for the first time.
Use like this:
import React, { useEffect } from 'react'
export default function App () {
useEffect(() => {
// this code will run once
}, [])
// ...
}
React-Native has a function super() which is same as constructor() that will work when your application get started. For example if you write a alert message on your super() function('When a user open your app, an alert message will be display'. You are able to get data using super() function when your app is opened)
super(){
alert('app started')
}

React Hook setState not set on promise

I'm using the Contentful CMS JS SDK and the code below does not update my React Hook state. It's more of a promises combined with react hooks combined with React render issue - I believe. I understand that the promise sets the hook value when it is resolved at a later time, but by that time my component already rendered with the initial data (empty string), so if this is the case, how can I make my component re-render when the react hook state is set with the correct value from the promise, so that my Button displays it.
Any help appreciated. Thanks
Problem lies within here.
...
import client from 'contentful'
const [name, setName] = useState('')
client.getEntry(data.fields.store.sys.id)
.then(entry => setName(entry.fields.name))
.catch(console.error)
console.log('STORE URL', name) // name is not set
...
<Button title={name} /> // name still not set
....
I just tried your code and it seems to work for me. :)
https://codesandbox.io/embed/react-hooks-demo-e4wgo
I think you should use useEffect though as described in this article.