Having trouble with variables (this.x) in react native - react-native

I'm following this tutorial to try to get tensorflow js working in react native.
The tutorial's code is as follows (working, tested by cloning the repo):
class App extends React.Component {
state = {
isTfReady: false,
isModelReady: false,
predictions: null,
image: null
}
async componentDidMount() {
await tf.ready()
this.setState({
isTfReady: true
})
this.model = await mobilenet.load()
this.setState({ isModelReady: true })
this.getPermissionAsync()
}
While my code:
const modelJson = require('../assets/model/model.json');
const modelWeights = require('../assets/model/group1-shard1of1.bin');
class CameraCompo extends Component {
async componentDidMount(){
this.model = await tf.loadGraphModel(bundleResourceIO(modelJson, modelWeights));
}
Gives me the error: Property 'model' does not exist on type 'CameraCompo'
I've tried adding this.model into a constructor, as follows:
constructor(props){
super(props)
this.model = tf.GraphModel
}
But then, it simply gives me the same error.
Any help would be greatly appreciated.

Typescript is complaining that model is not a property of the component
An interface can be defined for the props and the state for typescript to infer them along the way. If not they can be simply set to any which defeats the purpose of using typescript
inferface Props {
// add what is necessary
}
interface State {
model: any
}
class CameraCompo extends Component<Props, State> {
async componentDidMount(){
const model = await tf.loadGraphModel(bundleResourceIO(modelJson, modelWeights));
this.setState(model)
// later model can be accessed with this.state.model.predict(input)
}
}
The above would be to define a model and set it in the state of the component. But the model hardly changes and there might probably not a need to keep it in the state of the component. In that case, model simply needs to be declared
class CameraCompo extends Component {
private model: any
async componentDidMount(){
this.model = await tf.loadGraphModel(bundleResourceIO(modelJson, modelWeights));
}
}

Related

render is called before the asynchronous method has finished in react native

hi everyone i am recently learning react native and i have a synchronization problem sending data from one screen to another screen.
I have the parent page (UserList) that wants to send its status to the child page (RecyclerViewPage) but the render is called before the data is available.
export default class UserList extends Component {
constructor(props){
super(props);
this.state={
comment_state: [],
datetime: []
}
}
//getPost is a network call which gets and store the result in the state of the class
async getPost(){
var sid=this.props.route.params.value_sid
var did=this.props.route.params.value_did
const utils=new Utils();
const responseJson = await utils.getPost(sid,did)
const comment = (responseJson?.posts ?? []).map((data) => data.comment)
this.setState({comment_state:comment})
console.log("now i change state with new value")
}
componentDidMount(){
this.getPost()
}
render(){
return(
<RecyclerViewPage
comment={this.state.comment_state}
/>
)
}
}
and RecyclerViewPage code:
export default class RecyclerViewPage extends Component {
constructor(props) {
super(props);
console.log("i am in recyclerviewPage : ",this.props.comment)
}
render(){}
}
I tried to put some logs and the result is:
Log: "i am in recyclerviewPage: []"
Log: "now i change state with new value"
It appears as if render () was called before the asynchronous getPost method has finished. how can i synchronize my code in order to get the data first and then send it to the RecyclerViewPage daughter schemata?
See you can wait for the results and then show recyclerviewpage:
You can add a loader state while its being fetched:)
Hope it helps. feel free for doubts
export default class UserList extends Component {
constructor(props){
super(props);
this.state={
comment_state: [],
datetime: []
}
}
//getPost is a network call which gets and store the result in the state of the class
async getPost(){
var sid=this.props.route.params.value_sid
var did=this.props.route.params.value_did
const utils=new Utils();
const responseJson = await utils.getPost(sid,did)
const comment = (responseJson?.posts ?? []).map((data) => data.comment)
this.setState({comment_state:comment})
console.log("now i change state with new value")
}
componentDidMount(){
this.getPost()
}
render(){
return(
{!!comment_state && <RecyclerViewPage
comment={this.state.comment_state}
/> }
{!comment_state && <Text> Please wait its loading </Text>}
)
}
}

TypeError: undefined is not an object (evaluating '_this2.setState')

I encountered an error code while working on the project.
The error codes I face are as follows.
TypeError: undefined is not an object (evaluating '_this2.setState')
And this is my source code.
export default class MainScreen extends Component {
state = {currentSound:''};
getData() {
AsyncStorage.getItem('soundState', (err, result) => {
const soundSt = JSON.parse(result);
this.setState({currentSound:soundSt.soundNumber});
});
}
}
How can I solve this problem?
I think this is because getData()is not binded to the current scope oy the class. Fix it by using arrow function:
export default class MainScreen extends Component {
state = {currentSound:''};
getData = () => {
AsyncStorage.getItem('soundState', (err, result) => {
const soundSt = JSON.parse(result);
this.setState({currentSound:soundSt.soundNumber});
});
}
}

Connexion object singleton in react native

I'm trying to create a singleton service class in which I instanciate a connection object, which connect to the backend, in order to reuse the connection object in every component, so I've done that:
const {
Kuzzle,
WebSocket
} = require('kuzzle-sdk');
class KuzzleService {
static instance = null;
static async createInstance() {
var object = new KuzzleService();
object.kuzzle = new Kuzzle(
new WebSocket('localhost'),{defaultIndex: 'index'}
);
await object.kuzzle.connect();
const credentials = { username: 'user', password: 'pass' };
const jwt = await object.kuzzle.auth.login('local', credentials);
return object;
}
static async getInstance () {
if (!KuzzleService.instance) {
KuzzleService.instance = await KuzzleService.createInstance();
}
return KuzzleService.instance;
}
}
const kuzzleService = KuzzleService.getInstance();
export default kuzzleService;
But when I import the service in a component as follow:
import kuzzleService from "../services/kuzzle-service.js";
And I print that:
async componentDidMount(){
console.log(JSON.stringify(kuzzleService.kuzzle));
}
It gives me "undefined". Should I import the service another way ?
This is probably because when you export kuzzleService, the promise given by .getInstance() isn't resolved yet.
You should export the .getInstance function and await it in componentDidMount, like that:
export default KuzzleService; // export the singleton directly
async componentDidMount(){
const kuzzle = await KuzzleService.getInstance();
console.log(kuzzle);
}

Validate React Native Component with Asynchronous Work

I have a basic component that calls a webservice during the componentDidMount phase and overwrites the contents value in my state:
import React, {Component} from 'react';
import {Text} from "react-native";
class Widget extends Component {
constructor() {
super();
this.state = {
contents: 'Loading...'
}
}
async componentDidMount() {
this.setState(...this.state, {
contents: await this.getSomeContent()
});
}
render() {
return (
<Text>{this.state.contents}</Text>
)
}
async getSomeContent() {
try {
return await (await fetch("http://someurl.com")).text()
} catch (error) {
return "There was an error";
}
}
}
export default Widget;
I would like to use Jest snapshots to capture the state of my component in each one of the following scenarios:
Loading
Success
Error
The problem is that I have to introduce flaky pausing to validate the state of the component.
For example, to see the success state, you must place a small pause after rendering the component to give the setState method a chance to catch up:
test('loading state', async () => {
fetchMock.get('*', 'Some Content');
let widget = renderer.create(<Widget />);
// --- Pause Here ---
await new Promise(resolve => setTimeout(resolve, 100));
expect(widget.toJSON()).toMatchSnapshot();
});
I'm looking for the best way to overcome the asynchronicity in my test cases so that I can properly validate the snapshot of each state.
If you move the asynchronous call out of setState, you can delay setState until the network call has resolved. Then you can use setState's optional callback (which fires after the state change) to capture the state.
So, something like this:
async componentDidMount() {
var result = await this.getSomeContent()
this.setState(...this.state, {
contents: result
},
// setState callback- fires when state changes are complete.
()=>expect(this.toJSON()).toMatchSnapshot()
);
}
UPDATE:
If you want to specify the validation outside of the component, you could create a prop, say, stateValidation to pass in a the validation function:
jest('loading state', async () => {
fetchMock.get('*', 'Some Content');
jestValidation = () => expect(widget.toJSON()).toMatchSnapshot();
let widget = renderer.create(<Widget stateValidaton={jestValidation}/>);
});
then use the prop in the component:
async componentDidMount() {
var result = await this.getSomeContent()
this.setState(...this.state, {
contents: result
},
// setState callback- fires when state changes are complete.
this.props.stateValidaton
);
}

Error modal sample with super outside constructor

Anyone can help me fix this error when using code modal sample in link https://facebook.github.io/react-native/docs/modal.html I can't understand why this error appear although i coded absolutely same code sample.
Use ES6 class. Constructor will work only on ES6 class.
class ModalExample extends React.Component {
constructor () {
super(props)
}
render () {
// code
}
}
If you don't want to use ES6 class, then use getInitialState to set the state.
var ModalExample = React.createClass ({
getInitialState: function() {
return {
modalVisible: false
}
}
})