I'm trying to combine react-native and meteor using the react-native-meteor package. Meteor successfully publishes a 'dos' collection, which I have been able to subscribe to on the web client. However, after following the documentation of the react-native-meteor package (using createContainer) I am unable to subscribe; the handle is 'never ready'. When using the autopublish package from Meteor the data does load.
Versions
Meteor 1.3.4.1
react-native: 0.28.0
react-native-meteor: 1.0.0-rc14
index.ios.js
// #flow
'use strict'
import React, { Component } from 'react'
import {
AppRegistry,
StyleSheet,
View,
NavigatorIOS,
StatusBar,
Text,
} from 'react-native'
import Meteor, {
createContainer,
MeteorListView,
} from 'react-native-meteor'
Meteor.connect('ws://localhost:3000/websocket')
import GeoLocation from './app/GeoLocation'
import ConnectionInfoSubscription from './app/NetInfo'
import GridLayout from './app/GridLayout'
class DoCHANGE_0 extends Component {
renderRow(Do){
return(
<Text>{Do.joke}</Text>
)
}
render() {
const { doList, } = this.props
return (
<View style={styles.container}>
<StatusBar
barStyle="light-content"
/>
<NavigatorIOS
style = {styles.container}
barTintColor='#556270'
titleTextColor='#fff'
tintColor='#fff'
initialRoute={{
title: 'DoCHANGE',
component: GridLayout
}}/>
{!doList && <Text>Not ready with subscription</Text>}
<MeteorListView
collection="dos"
renderRow={this.renderRow}
enableEmptySections={true}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex:1,
}
});
export default createContainer(params=>{
const handle = Meteor.subscribe('dos')
return {
doList: handle.ready(),
};
}, DoCHANGE_0)
AppRegistry.registerComponent('DoCHANGE_0', () => DoCHANGE_0);
I have found similar examples but they often don't utilise the react-native-meteor package but use the ddpclient package instead. Am I missing something obvious here? Any insights is much appreciated!
Edit:
(Meteor) /server/publish.js
Meteor.publish("dos", function() {
//console.log(Dos.find().fetch())
return Dos.find();
})
(Meteor) /both/collections.js
Dos = new Mongo.Collection('dos');
Screenshot when using autopublish from Meteor. doList handle is still not ready. But the MeteorList gets populated correctly.
Screenshot iOS autopublish on
You only included client side code in your question, but it sounds like you are missing the Meteor.publish() call on the server, if it works using autopublish but not without it!
I upgraded to newer versions of react-native, meteor, and react-native-meteor but that didn't solve the issue. However, when renaming the renderRow function to renderItem it started working.
renderRow={this.renderRow}
renderRow={this.renderItem}
Related
Hi I had simple snapshot test but I needed to save data from API with redux toolkit and after that it's always failing.
DashboardScreen.tsx
const DashboardScreen = () => {
// added block of code
const dispatch = useDispatch();
const { data: userData } = useGetUserDataQuery();
useEffect(() => {
if (userData) dispatch(setCurrentUser(userData));
}, [dispatch, userData]);
// end of added block of code
return (
<View style={styles.container}>
<View style={styles.containerWidth}>
<Image
style={styles.logo}
source={require('../../assets/images/KonektoSmart-logo.png')}
/>
</View>
</View>
);
};
and the test DashboardScreen-test-tsx
test('renders correctly', () => {
const tree = create(<DashboardScreen />).toJSON();
expect(tree).toMatchSnapshot();
});
● Test suite failed to run - but I tried some of the under and doesn't work.
[#RNC/AsyncStorage]: NativeModule: AsyncStorage is null.
To fix this issue try these steps:
• Run `react-native link #react-native-async-storage/async-storage` in the project root.
• Rebuild and restart the app.
• Run the packager with `--reset-cache` flag.
• If you are using CocoaPods on iOS, run `pod install` in the `ios` directory and then rebuild and re-run the app.
• If this happens while testing with Jest, check out docs how to integrate AsyncStorage with it: https://react-native-async-storage.github.io/async-storage/docs/advanced/jest
To solve this problem I needed to use Provider. For me docs are unclear doing that.
Full code:
import React from 'react';
import { create } from 'react-test-renderer';
import DashboardScreen from '../DashboardScreen';
import { Provider } from 'react-redux';
import store from '../../redux/store';
test('renders correctly', async () => {
const tree = create(<Provider store={store}><DashboardScreen /></Provider>).toJSON();
expect(tree).toMatchSnapshot();
});
I'm having a bit of difficulty implementing redux in a simple react project that I'm creating. For clarification, it's a react 360 webvr project but I've seen many similarities with react native that I'm sure this can work.
The project that I'm trying to do is simply changing the background color of a component on the click of a button. Below is my code:
constants.js
export const PICK_COLOR = 'PICK_COLOR';
actions.js
import { PICK_COLOR } from './constants'
export const pickColor = (color) => ({
type: PICK_COLOR,
payload: color
})
reducers.js
import { PICK_COLOR } from './constants';
const initialColor = {
backgroundColor: 'white'
}
export const chooseColor = (state = initialColor, action={}) => {
switch (action.type) {
case PICK_COLOR:
return Object.assign({}, state, {backgroundColor: action.payload})
default:
return state
}
}
index.js
import React from 'react';
import { createStore } from 'redux';
import { Provider, connect } from 'react-redux';
import { chooseColor } from './reducers';
import { pickColor } from './actions';
import {
AppRegistry,
StyleSheet,
Text,
View,
VrButton
} from 'react-360';
const store = createStore(chooseColor);
const mapStateToProps = state => {
return {
backgroundColor: state.chooseColor.backgroundColor
}
}
const mapDisptachToProps = (dispatch) => {
return {
onChooseColor: (event) => dispatch(pickColor(event.target.value))
}
}
class App extends React.Component {
render() {
const { backgroundColor, onChooseColor } = this.props;
return (
<Provider store={store}>
###########################################
I want this to change background color with
the click of a button.
<View style={[styles.panel, backgroundColor: this.props.backgroundColor]}>
###########################################
<VrButton style={styles.greetingBox} onClick={onChooseColor('blue')}>
<Text style={[styles.greeting, {color: 'blue'}]}>
Blue
</Text>
</VrButton>
</View>
</Provider>
);
}
};
const connectedApp = connect(mapStateToProps, mapDisptachToProps)(App);
AppRegistry.registerComponent('App', () => App);
The problem I'm having is getting over the finish line. I think I have everything set up almost correctly, but I'm unable to trigger any state change. The part where I'm getting confused is how do I connect my onClick prop handler to a state change and pass an argument? I've mixed and matched so many tutorials and videos that my head is spinning at the moment and I'm not entirely wrapping my head about setting up redux yet to troubleshoot effectively.
From what I've gathered, I don't think I have my mapDispatchToProps correctly because in the console I get the error that OnChooseColor is not a function. But how am I supposed to trigger the change? Can someone help pinpoint where I am going wrong? The help would be appreciated.
Could it be that in your mapStateToProps you are reading from state.chooseColor.backgroundColor, but it looks like your store has the shape state.backgroundColor (from what I can tell by the reducers.js)?
It's a bit late for me, so I'll probably have a look at this again tomorrow! (I'll try being more hands-on than just staring at the code!). But I'd definitively try to debug your store in your browser, by setting some breakpoints and having a look at what the store contains. There's also some handy browser extensions for react and redux that I would try out as well! (they should in theory make it easier to see what's going on with redux & react).
I can at least vouch for the react extension myself, I use it heavily just for the feature of being able to tell me which React component I'm looking at (as the DOM renders into <div> and not <MyComponent>!)
Edit: I made a small example that's very similar to this one here!
Two things I can spot by scanning your code.
1. backgroundColor is on the state in reducer.
const mapStateToProps = state => {
return {
backgroundColor: state.backgroundColor
}
}
The function for onClick should be passed instead of calling it.
onClick={() => onChooseColor('blue')}
I am using laravel as my back-end and I've tested all the method and it works tho. I already test it using postman for my laravel as a backend and it works. But when I try it in react native it didnt work at all. I'm still new to react native.
Here's my code for PinjamList.js in RN:
import React, {Component} from 'react';
import {View, Text, StyleSheet} from 'react-native';
import PropTypes from 'prop-types';
export default class PinjamList extends Component {
static propTypes = {
pinjams: PropTypes.array.isRequired
};
render() {
return ({
this.props.pinjams.map((pinjam) => {
return ({pinjam.ketua_kegiatan} | {pinjam.lab})
})
});
}
}
const styles = StyleSheet.create({
pinjamList: {
flex: 1,
flexDirection: 'column',
justifyContent: 'space-around',
},
pinjamtext: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
}
});
And this one is js file for fetching the data:
const URI = 'http://localhost:8000';
export default {
async fetchDataPinjam() {
try {
let response = await fetch(URI + '/api/pinjams');
let responseJsonData = await response.json();
return
responseJsonData;
} catch (e) {
console.log(e);
}
}
}
And this one is the code for displaying the data on the homepage:
<View> { this.state.pinjams.length > 0
? <PinjamList pinjams={this.state.pinjams} />
: <Text>Tidak Ada Peminjaman</Text> } </View>
But when I try to test it to make sure if its right, this error shown:
Network request failed
- node_modules\react-native\Libraries\vendor\core\whatwg-fetch.js:504:29 in onerror
- node_modules\event-target-shim\lib\event-target.js:172:43 in dispatchEvent
- ... 8 more stack frames from framework internals
First thing : the API what is the HTTP method ?
Second thing : if the method is get please add screen shot about results from your browser or postman
Anyway, It's Fixed already,,... I got stuck because of missing expression somehow... so sorry ... and Thank you for helping me out.
For those who are using their smartphone to compile the application, please do check the IP Address, make sure your Phone and Laptop are connected with the same network, and do multiple checking on your code if there is something wrong with your app...
THANK YOU -
I am trying to create a slider menu with the react-native-drawer-menu module. After installing the module . get an error can`t find variable styles. This is the code copied from the example:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux'
import'../I18n/I18n.js';
import RootContainer from './RootContainer'
import createStore from '../Redux'
import Drawer from 'react-native-drawer-menu';
import {Easing} from 'react-native'; // Customize easing function (Optional)
// create store
const store = createStore()
export default class App extends React.Component {
render() {
// prepare your drawer content
var drawerContent = (<View style={styles.drawerContent}>
<View style={styles.leftTop}/>
<View style={styles.leftBottom}>
<View><Text>Drawer Content</Text></View>
</View>
</View>);
var customStyles = {
drawer: {
shadowColor: '#000',
shadowOpacity: 0.4,
shadowRadius: 10
},
mask: {}, // style of mask if it is enabled
main: {} // style of main board
};
return (
<Drawer
style={styles.container}
drawerWidth={300}
drawerContent={drawerContent}
type={Drawer.types.Overlay}
customStyles={{drawer: styles.drawer}}
drawerPosition={Drawer.positions.Right}
onDrawerOpen={() => {console.log('Drawer is opened');}}
onDrawerClose={() => {console.log('Drawer is closed')}}
easingFunc={Easing.ease}
>
<View style={styles.content}>
<Text>{Object.values(Drawer.positions).join(' ')}</Text>
<Text>{Object.values(Drawer.types).join(' ')}</Text>
</View>
</Drawer>
);
}
}
If I delete the variable from the code then the slide menu works but looks extremely bad.
Do you think that I am supposed to create the style of the menu on my own or shall I imported from somewhere? If I have to create it, how can I know which parameters did it take? Or is it a normal view?
Looks like you have to add styles by yourself to make look Drawer content exactly as you want to. To achieve it you have to create Stylesheet
You can use this answer to get more info about React Native Stylesheet properties (it's pretty much similar to css)
Also maybe this example from drawer repo would be helpful
Cheers.
I can't seem to get createContainer to work with React Native and Meteor data. I'm currently using the react-native-meteor package and the latest releases of Meteor/React Native. I've reviewed the info for the package and Meteor's official write-up of createContainer. I guess first off, I'm not really sure how this container works. It looks like it wraps the component called at the end and updates it when the reactive data changes?
I've tried it a few different ways but below is what I currently am using. I'm not sure if createContainer is even getting called, as I don't see anything in the console from my log statement. I've tried using Meter.user() and Meteor.userId() as well with no luck. Any idea as to what I'm doing wrong?
'use strict';
import React, { Component } from 'react'
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import { loginToSpotify } from './react-native-spotify-auth'
import Meteor, { createContainer } from 'react-native-meteor'
//import { testComponent } from './component'
//TODO: openURL bug on iOS9 causes iOS to confirm before redirect: http://stackoverflow.com/questions/32312009/how-to-avoid-wants-to-open-dialog-triggered-by-openurl-in-ios-9-0
//May also want to look into using Universal links
Meteor.connect('http://localhost:3000/websocket');//do this only once
class ReactNativeApp extends Component {
constructor(props) {
super(props);
this.state = {
access_token: null
};
}
componentDidMount() {
loginToSpotify();
}
render() {
const { todosReady } = this.props;
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
<Text>
Hello {!todosReady && <Text>Not Ready</Text>}
</Text>
</View>
);
}
}
export default createContainer(params=>{
const handle = Meteor.subscribe('todos');
console.log('todos: ' + Meteor.collection('todos').find());
return {
todosReady: handle.ready()
}
}, ReactNativeApp);
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5
}
});
AppRegistry.registerComponent('ReactNativeApp', () => ReactNativeApp);
Can you see in console that meteor connected to the app? You shouldn't use http in Meteor.connect anymore, instead ws://localhost:3000/websocket
Be sure that your meteor application is running.
Use the IP of your local machine, don't use localhost. If you are using mobile as emulator that's good. Connect both in Router and use your machine language.
For more information you can follow this React Native Meteor Boilerplate.