facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.82k stars 24.29k forks source link

Cannot assign to read only property 'props' of #<Object> #4281

Closed Sharathnasa closed 8 years ago

Sharathnasa commented 8 years ago

1654

Hi @ide @brentvatne @vjeux ,

Im having this issue-

Cannot assign to read only property 'props' of #<Object>

I checked #1654 with no success. Please have a look at the issue in more detail here-

screen shot 2015-11-22 at 5 30 24 pm

And chrome debug messages-

screen shot 2015-11-22 at 5 31 16 pm

Basically what I am doing is using a Navigator to move from index page to ApplistGridView page. I see the navigation is successful(from logs) but, even before I see the screen I face this issue.

What am I doing wrong?

// cc @bozzmob

satya164 commented 8 years ago

Mind posting the code?

Sharathnasa commented 8 years ago

@satya164 Here are my code snippets.

index.js

'use strict';

var React = require('react-native');
var Subscribable = require('Subscribable');

var PAGES = 3;
var BGCOLOR = ['#F3F781', '#D8F781', '#E6E6E6'];
var IMAGE_URIS = [
  'https://lh4.ggpht.com/JJ5Q0-B7P52tQqaz9m7ZEq9cpIOCpDZqLccODNuOl3FOo_bbx5yfoDbFRVbfuJSFHHY=w300',
  'https://lh3.googleusercontent.com/EkPYk0aq6xKrERKrde2jFChOh5S3wewzW-cKy1pck8YFu8ZIAx3kjsG45wZYi5-khUY=w300',
  'https://lh3.googleusercontent.com/mkfH6NV_uISCI88anQnaDIy9upOqLSf-9LzQ7bqEgPSRqZ31OxjdJHOZIa4OXucE8w=w300',
  'https://pbs.twimg.com/profile_images/518624830216626177/nP44m-lm.png',
  'https://lh3.ggpht.com/RKLFoqtI43iNDEp8_xbCoHdHQnc_iUDH90kW_j2yH_x6U_PnL9jWQ4X4ZBhH0zxkgg=w300',
];

var {
  Image,
  StyleSheet,
  AppRegistry,
  Text,
  TouchableWithoutFeedback,
  TouchableOpacity,
  View,
  Navigator,
  ViewPagerAndroid,
} = React;

var LikeCount = React.createClass({
  getInitialState: function() {
    return {
      likes: 7,
    };
  },
  onClick: function() {
    this.setState({likes: this.state.likes + 1});
  },
  render: function() {
    var thumbsUp = '\uD83D\uDC4D';
    return (
      <View style={styles.likeContainer}>
        <TouchableOpacity onPress={this.onClick} style={styles.likeButton}>
          <Text style={styles.likesText}>
            {thumbsUp + ' Like'}
          </Text>
        </TouchableOpacity>
        <Text style={styles.likesText}>
          {this.state.likes + ' likes'}
        </Text>
      </View>
    );
  },
});

var Button = React.createClass({
  _handlePress: function() {
    if (this.props.enabled && this.props.onPress) {
      this.props.onPress();
    }
  },
  render: function() {
    return (
      <TouchableWithoutFeedback onPress={this._handlePress}>
        <View style={[styles.button, this.props.enabled ? {} : styles.buttonDisabled]}>
          <Text style={styles.buttonText}>{this.props.text}</Text>
        </View>
      </TouchableWithoutFeedback>
    );
  }
});

var ProgressBar = React.createClass({
  render: function() {
    var fractionalPosition = (this.props.progress.position + this.props.progress.offset);
    var progressBarSize = (fractionalPosition / (PAGES - 1)) * this.props.size;
    return (
      <View style={[styles.progressBarContainer, {width: this.props.size}]}>
        <View style={[styles.progressBar, {width: progressBarSize}]}/>
      </View>
    );
  }
});

var homescreen = React.createClass({

  statics: {
    title: 'sahasraa launcher',
    description: 'AI launcher'
  },
  getInitialState: function() {
    return {page: 0, progress: {position: 0, offset: 0}};
  },
  onPageSelected: function(e) {
    this.setState({page: e.nativeEvent.position});
  },
  onPageScroll: function(e) {
    this.setState({progress: e.nativeEvent});
  },
  move: function(delta) {
    var page = this.state.page + delta;
    this.viewPager && this.viewPager.setPage(page);
    this.setState({page});
  },
  go: function(page) {
    this.viewPager && this.viewPager.setPage(page);
    this.setState({page});
  },
  render: function() {
    var pages = [];
    for (var i = 0; i < PAGES; i++) {
      var pageStyle = {
        backgroundColor: BGCOLOR[i % BGCOLOR.length],
        alignItems: 'center',
        padding: 20,
      };
        pages.push(
            <View key={i} style={pageStyle} collapsable={false}>
            <Image
              style={styles.image}
              source={{uri: IMAGE_URIS[i % BGCOLOR.length]}}
            />
            <LikeCount />
          </View>
         );
    }
    var page = this.state.page;
    return (
      <View style={styles.container}>
        <View style={styles.buttons}>
          <Button text="Start" enabled={page > 0} onPress={() => this.go(0)}/>
          <Button text="Prev" enabled={page > 0} onPress={() => this.move(-1)}/>
          <Text style={styles.buttonText}>Page {page + 1} / {PAGES}</Text>
          <ProgressBar size={100} progress={this.state.progress}/>
          <Button text="Next" enabled={page < PAGES - 1} onPress={() => this.move(1)}/>
          <Button text="Last" enabled={page < PAGES - 1} onPress={() => this.go(PAGES - 1)}/>
        </View>
        <View style={styles.buttons}>
          <Button text="Apps" enabled={PAGES} onPress={() => this.pushApplist()}/>
        </View>
        <ViewPagerAndroid
          style={styles.viewPager}
          initialPage={0}
          onPageScroll={this.onPageScroll}
          onPageSelected={this.onPageSelected}
          ref={viewPager => { this.viewPager = viewPager; }}>
          {pages}
        </ViewPagerAndroid>
      </View>
    );
  },
  pushApplist: function() {
    console.log("inside pushApplist");
    this.props.nav.push({id: 'Applist', index: 2});
  },
});

var styles = StyleSheet.create({
  buttons: {
    flexDirection: 'row',
    height: 30,
    backgroundColor: 'black',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  button: {
    flex: 1,
    width: 0,
    margin: 5,
    borderColor: 'gray',
    borderWidth: 1,
    backgroundColor: 'gray',
  },
  buttonDisabled: {
    backgroundColor: 'black',
    opacity: 0.5,
  },
  buttonText: {
    color: 'white',
  },
  container: {
    flex: 1,
    backgroundColor: 'white',
  },
  image: {
    width: 300,
    height: 200,
    padding: 20,
  },
  likeButton: {
    backgroundColor: 'rgba(0, 0, 0, 0.1)',
    borderColor: '#333333',
    borderWidth: 1,
    borderRadius: 5,
    flex: 1,
    margin: 8,
    padding: 8,
  },
  likeContainer: {
    flexDirection: 'row',
  },
  likesText: {
    flex: 1,
    fontSize: 18,
    alignSelf: 'center',
  },
  progressBarContainer: {
    height: 10,
    margin: 10,
    borderColor: '#eeeeee',
    borderWidth: 2,
  },
  progressBar: {
    alignSelf: 'flex-start',
    flex: 1,
    backgroundColor: '#eeeeee',
  },
  viewPager: {
    flex: 1,
  },
});

module.exports = homescreen;

ApplistGridView.js

'use strict';

var React = require('react-native');
var Subscribable = require('Subscribable');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var {
  Image,
  ListView,
  TouchableHighlight,
  StyleSheet,
  AppRegistry,
  Text,
  ListView
} = React;

var THUMB_URLS = [
  'https://en.opensuse.org/images/1/1d/Skype-icon-128x128.png',
  'http://www.openwebanalytics.com/wp-content/plugins/owa/modules/base/i/browsers/128x128/ie4.png',
  'http://e38.ru/files/imagecache/192x192/files/pictures/picture-2293.jpg',
  'http://mib.pianetalinux.org/blog/images/stories/d/darktable-128x128.png',
  'http://kansascitysnowcones.com/wp-content/uploads/2012/06/128x128-youtube.png',
  'http://vectorlogo.biz/wp-content/uploads/2013/01/NEW-INTEL-VECTORLOGO-DOT-BIZ-128x128.png',
  'http://www.iconesbr.net/iconesbr/2008/08/4328/4328_128x128.png',
  'http://www.justinparks.com/wp-content/uploads/2009/10/google-badge-128x128.png',
  'http://citruspay.com/DevelopersGuide/citrusjs/images/logo@2x.png',
  'https://bitbucket-assetroot.s3.amazonaws.com/c/photos/2014/May/02/coronium-mongo-demo-logo-469707550-0_avatar.png',
  'http://www.mstoic.com/wp-content/uploads/2013/07/Speed-128x128.png',
  'http://icons.iconarchive.com/icons/giannis-zographos/german-football-club/128/Eintracht-Frankfurt-icon.png',
];

var appListDetails = require('./AppList');

appListDetails.show(
  (msg) => { console.log(msg); },
   (result) => { console.log(result); }
  );

var ApplistGrid = React.createFactory(React.createClass({
 mixins: [Subscribable.Mixin],

  statics: {
    title: 'App ListView Grid Layout',
    description: 'Applist grid layout.'
  },

  getInitialState: function() {
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    return {
      dataSource: ds.cloneWithRows(this._genRows({})),
    };
  },

  _pressData: ({}: {[key: number]: boolean}),

  componentWillMount: function() {
    this._pressData = {};
  },

  render: function() {
    return (
      // ListView wraps ScrollView and so takes on its properties.
      // With that in mind you can use the ScrollView's contentContainerStyle prop to style the items.
      <ListView
        contentContainerStyle={styles.list}
        dataSource={this.state.dataSource}
        renderRow={this._renderRow}/>
    );
  },

  _renderRow: function(rowData: string, sectionID: number, rowID: number) {
    var rowHash = Math.abs(hashCode(rowData));
    var imgSource = {
      uri: THUMB_URLS[rowHash % THUMB_URLS.length],
    };
    return (
      <TouchableHighlight onPress={() => this._pressRow(rowID)} underlayColor="transparent">
        <View>
          <View style={styles.row}>
            <Image style={styles.thumb} source={imgSource} />
            <Text style={styles.text}>
              {rowData}
            </Text>
          </View>
        </View>
      </TouchableHighlight>
    );
  },

  _genRows: function(pressData: {[key: number]: boolean}): Array<string> {
    var dataBlob = [];
    for (var ii = 0; ii < 100; ii++) {
      var pressedText = pressData[ii] ? ' (X)' : '';
      dataBlob.push('Cell ' + ii + pressedText);
    }
    return dataBlob;
  },

  _pressRow: function(rowID: number) {
    this._pressData[rowID] = !this._pressData[rowID];
    this.setState({dataSource: this.state.dataSource.cloneWithRows(
      this._genRows(this._pressData)
    )});
  },
}));

/* eslint no-bitwise: 0 */
var hashCode = function(str) {
  var hash = 15;
  for (var ii = str.length - 1; ii >= 0; ii--) {
    hash = ((hash << 5) - hash) + str.charCodeAt(ii);
  }
  return hash;
};

var styles = StyleSheet.create({
  list: {
    justifyContent: 'space-around',
    flexDirection: 'row',
    flexWrap: 'wrap'
  },
  row: {
    justifyContent: 'center',
    padding: 5,
    margin: 3,
    width: 100,
    height: 100,
    backgroundColor: '#F6F6F6',
    alignItems: 'center',
    borderWidth: 1,
    borderRadius: 5,
    borderColor: '#CCC'
  },
  thumb: {
    width: 64,
    height: 64
  },
  text: {
    flex: 1,
    marginTop: 5,
    fontWeight: 'bold'
  },
});

module.exports = ApplistGrid;

So basically, I am making a transition from button in index.js to ApplistGridView.js

Using this in the Navigator code-

if (route.id === 'Applist') {
      console.log("ApplistGridView scene = "+JSON.stringify(ApplistGridView));
      console.log("Applist - route= "+route+" navigator= "+navigator);
      return (
        <View style={{flex: 1}}>
        <NavToolbar navigator={navigator}/>
        //<ApplistGridView index = {route.index} post={route.post} nav={navigator}  />
        <ApplistGridView index = {route.index} nav={navigator}  />
        </View>
      )
    }
FaridSafi commented 8 years ago

I don't know if it can solve your problem but you can try to JSX comment using: {/* comment */} instead of: //

bozzmob commented 8 years ago

@satya164 Please can you have a look at it. There is no much of code change from original version, but, still facing error. @FaridSafi Tried it. Not working still.

satya164 commented 8 years ago

@bozzmob The overal code looks correct, except the comment @FaridSafi mentioned. It'll be of some help if we can see the aourcemaps in the redbox/error message above. Is source map not working for you? When you're loading from packager server, it might take a little while to show up.

bozzmob commented 8 years ago

@satya164 Thanks. I had not seen that place yet. The logs from react-native start

Looking for JS files in
   /home/bozzmob/Purvotara/sahasraa/sahasraa 

[8:47:51 AM] <START> Building Dependency Graph
[8:47:51 AM] <START> Crawling File System
[8:47:51 AM] <START> Loading bundles layout
[8:47:51 AM] <END>   Loading bundles layout (0ms)

React packager ready.

[8:47:57 AM] <END>   Crawling File System (6307ms)
[8:47:57 AM] <START> Building in-memory fs for JavaScript
[8:47:58 AM] <END>   Building in-memory fs for JavaScript (856ms)
[8:47:58 AM] <START> Building Haste Map
[8:47:59 AM] <END>   Building Haste Map (1298ms)
[8:47:59 AM] <END>   Building Dependency Graph (8470ms)
[8:49:13 AM] <START> request:/index.android.bundle?platform=android&dev=true
[8:49:13 AM] <START> find dependencies
[8:49:14 AM] <END>   find dependencies (172ms)
[8:49:14 AM] <START> transform
transforming [========================================] 100% 324/324
[8:49:14 AM] <END>   transform (106ms)
[8:49:14 AM] <END>   request:/index.android.bundle?platform=android&dev=true (308ms)
 ::ffff:127.0.0.1 - - [24/Nov/2015:03:19:15 +0000] "GET /flow/ HTTP/1.1" 404 18 "-" "okhttp/2.4.0"
[8:49:29 AM] <START> request:/index.android.bundle?platform=android&dev=true
[8:49:29 AM] <END>   request:/index.android.bundle?platform=android&dev=true (20ms)
::ffff:127.0.0.1 - - [24/Nov/2015:03:19:31 +0000] "GET /flow/ HTTP/1.1" 404 18 "-" "okhttp/2.4.0"
[8:49:45 AM] <START> request:/index.android.bundle?platform=android&dev=true
[8:49:45 AM] <END>   request:/index.android.bundle?platform=android&dev=true (23ms)
::ffff:127.0.0.1 - - [24/Nov/2015:03:19:46 +0000] "GET /flow/ HTTP/1.1" 404 18 "-" "okhttp/2.4.0"

What does this mean-

"GET /flow/ HTTP/1.1" 404 18 "-" "okhttp/2.4.0"

A 404 and ok? 2 status codes or is it 404 alone? Please can you tell me what have I done wrong for it to throw a 404.

I am trying to open Listicons.js from the index.js(button click).

skevy commented 8 years ago

Hey @Sharathnasa, this is a question perfectly suited for StackOverflow: http://stackoverflow.com/questions/tagged/react-native

Many people from the community hang out there and will be able to see and answer your question, you can vote on answers and mark the question an answered, run bounties etc. It's a system that works really really well for questions. Keeping questions there lets us keep the list of bug reports and feature requests on github.

Please consider closing this issue in favor of asking your question on SO. :)

christopherdro commented 8 years ago

Hey there! Closing this issue since it's been tagged as a question appropriate for Stack Overflow. We are trying to keep GitHub issues strictly for bugs.

You can also try Product Pains where community members can vote on feature requests and bug repots.

Thanks!