加载组件时出现奇怪的错误

时间:2018-09-12 21:11:22

标签: javascript reactjs react-native

在尝试将第二个组件加载到我的app.js中时感到沮丧。我也有一个叫。我不断收到此错误,但我不明白为什么。 :

  

无法加载   捆绑包(http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false)   出现错误:(SyntaxError:   /Users/vemundeldegard/AwesomeProject/app/screens/Home.js:相邻JSX   元素必须包装在封闭标签中。您想要JSX吗   片段<> ...? (199:6)

将其加载到我的app.js中

import Comments from '../components/Comments'

<Comments
  addComment=""
/>

组件文件如下:

const Comments = (props) => {
  const styles = StyleSheet.create({
    container: {
      paddingLeft: 15,
      paddingRight: 15,
      flex: 1,
      flexDirection: 'row',
      justifyContent: 'space-between',
    },
    button: {
      padding: 10,
      height: 30,
      backgroundColor: "#eee"
    },
    buttonText: {
      fontSize:11
    },
    field: {
      fontSize:13,
      position: "relative",
      left: -3,
      top: -10,
    }
});
  return (
    <View style={styles.container}>
    <Input style={styles.field}
      autoCorrect={false}
      autoCapitalize="none"
      placeholder="Skriv en kommentar..."
    />
    <Button rounded style={styles.button} onPress={() => props.addComment()}>
      <Text style={styles.buttonText}>Kommenter</Text>
    </Button>
    </View>
  )
}
export Comments;

Whole app.js
import React, { Component } from 'react';
import * as firebase from 'firebase';
import {
  Alert,
  StyleSheet,
  Text,
  View,
  FlatList,
  ScrollView,
  Modal,
  TouchableHighlight,
  RefreshControl,
  Image
} from 'react-native';
import { Icon, Textarea, Container, Form, Content, Button, Input, Item, Label } from 'native-base';
import { firestore, settings } from '../Fire';
import moment from 'moment';
import Swiper from 'react-native-swiper';
import { RenderImage } from '../components/RenderImage'
import { Post } from '../components/Post'
import Comments from '../components/Comments'
export default class Home extends Component {

  constructor(props){
    super(props);
    this.state = {
      getData: [],
      liked: false,
      displayName:''
    }
    this.ref = firestore.collection("tips").orderBy("date", "desc");
  }


  state = { currentUser: null }


  signOutUser = () => {
    firebase.auth().signOut().then(function() {
      console.log("user signed out")
    }).catch(function(error) {
      console.log(error.toString())
    });
  }
  deleteAccount = () => {
    firebase.auth().currentUser.delete().then(function () {
      console.log('delete successful?')
      console.log(app.auth().currentUser)
    }).catch(function (error) {
      console.error({error})
    })
  }
  updateUser = (displayName) => {
    var user = firebase.auth().currentUser;
    let date = new moment().format("YYYYMMDD HHmmss");
      user.updateProfile({
        displayName: displayName,
        lastUpdated: date
      }).then(function() {
        alert("Updated!")
      }).catch(function(error) {
        alert("Error!")
      });
  }
  newTips = () => {
    let user = firebase.auth().currentUser;
    let name, email, photoUrl, uid, emailVerified, currentUser, displayName;
    let date = new moment().format("YYYYMMDD HHmmss");
    let tips=this.state.tips;

    firebase.auth().onAuthStateChanged(user => {

      if (user) {
        email = user.displayName;
        // User is signed in.
        console.log('Logged in user: ' + email)
        firestore.collection("tips").add({
            user: user.displayName,
            date: date,
            tips: tips,
            like: 0,
        })
        .then(function(docRef) {
            console.log("Document written with ID: ", docRef.id);
        })
        .catch(function(error) {
            console.error("Error adding document: ", error);
        });
      } else {
        // User is signed out.
        console.log('No user signed in')
      }
    })
  }

  componentDidMount(){
    this.getItems();
    const { currentUser } = firebase.auth();
    this.setState({ currentUser });
  }

  getItems = async () => {
    this.setState({ refreshing: true });
    this.unsubscribe = await this.ref.onSnapshot((querySnapshot) => {
          const todos = [];
          querySnapshot.forEach((doc) => {
            todos.push({
              id: doc.id,
              tips: doc.data().tips,
              date: doc.data().date,
              user: doc.data().user,
              like: doc.data().like,
            })
            this.ref.get().then(function(documentSnapshot) {
              // check and do something with the data here.
            });
          })
          this.setState({
            refreshing: false,
            getData: todos
          })
        })
  }



  likePost = (author, id) => {

    let user = firebase.auth().currentUser;
    let name, email, photoUrl, uid, emailVerified, currentUser, displayName;
    let date = new moment().format("YYYYMMDD HHmmss");

    firestore.collection("tips").doc(id).update({
      likes: {
          user: user.uid
      }
    })
    .then(function() {
        alert("Liked the post " + id)
    })
    .catch(function(error) {
        alert("Error writing document: ", user.uid, error);
    });
    this.liked()
  }
  liked(){
    this.setState({
      liked: !this.state.liked
    })
  }
  deletePost = (author, id) => {
    let user = firebase.auth().currentUser;
    const { currentUser } = this.state;
    const currentUsername = currentUser && currentUser.displayName;
    if (currentUsername == author) {
      Alert.alert(
  'Er du sikker?',
  'Du sletter nå denne posten...',
  [
    {text: 'Nei', onPress: () => {

    }, style: 'cancel'},
    {text: 'Ja', onPress: () => {
      firestore.collection("tips").doc(id).delete().then(function() {
           alert("Posten er slettet!")
       }).catch(function(error) {
           alert("Error removing document: ", error);
       });
    }},
  ]
);

     }
     else {
       alert("Not your post " + currentUsername  + " its " + author)
     }
  }
  viewComments = () => {
    alert("View Comments!!")
  }
  renderItem = ({ item, index }) => {
    return (
      <View>
      <Post
        author={item.user}
        date={ moment(item.date).fromNow() }
        entry={item.tips}
        likes={item.like}
        id={item.id}
        image="https://i.pinimg.com/originals/c5/89/19/c589198a4e4a4b2b54ebb3852ea4bd8b.jpg"
        commentCount="123"
        like={this.likePost}
        delete={this.deletePost}
        goComments={this.viewComments}
        liked={this.state.liked}
      />

      <Comments
        addComment=""
      />
      </View>
    )
  }
  _renderEmpty= () => {
    return (
      <Text>There is no tips...</Text>
    )
  }
  _renderFooter = () => {
    return (
      <Text>All tips has been loaded...</Text>
    )
  }
  _keyExtractor = (item, index) => item.id;
  _onRefresh = () => this.getItems();

  state = {
    modalVisible: false,
    refreshing: true, // whether comments list is being refreshed or not
  };
  render() {
    const { currentUser } = this.state
    return (
      <Swiper
        loop={false}
        showsPagination={false}
        index={1}
        ref='swiper'
      >
      <View style={share.container}>
      <Form>
      <Textarea
      ref= {(el) => { this.tips = el; }}
      onChangeText={(tips) => this.setState({tips})}
      value={this.state.tips}
        placeholderTextColor={'#FFF'}
        style={{ fontSize: 38, color: '#FFF'}}
        rowSpan={10}
        placeholder="Share your best vegan tips with people near you.."
        adjustsFontSizeToFit={true}
      />
      <Button
      rounded
      style={form.button}
      onPress={() => {
        this.newTips()
        this.refs.swiper.scrollBy(1)
      }
      }
    >
    <Text style={{color: '#FFF'}}>Share</Text>
    </Button>

  </Form>
      </View>
      <View style={styles.container}>
      <FlatList style={styles.flatlist}
        data={this.state.getData}
        renderItem={this.renderItem}
        ListEmptyComponent={this._renderEmpty}
        ListFooterComponent={this._renderFooter}
        keyExtractor={this._keyExtractor}
        refreshControl={
          <RefreshControl
            refreshing={this.state.refreshing}
            onRefresh={this._onRefresh}
          />
        }
      >
      </FlatList>
      </View>
      <View>
        <Text>3</Text>
      </View>
      </Swiper>
    );
  }
}
const profile = StyleSheet.create({
  container: {
    backgroundColor: '#EEF2E8',
    flex:1,
    paddingTop: 40,
    padding: 10,
  }
})
const title = StyleSheet.create({
  h1: {
    fontSize:32,
    color: "#70B21B",
    paddingLeft: 8,
    marginBottom: 10,
  }
})
const form = StyleSheet.create({
  input: {
    marginRight: 15,
  },
  button: {
    backgroundColor: '#ADDF6F',
    color: '#FFF',
    fontWeight: '600',
    paddingLeft: 20,
    paddingRight: 20,
    marginTop: 15,
    marginLeft: 10,
    marginRight: 10,
  }
})
const share = StyleSheet.create({
  container: {
    backgroundColor: '#D0E8B2',
    flex:1,
    paddingTop: 40,
    padding: 10,
  }
})
const modal = StyleSheet.create({
  container: {
    flex:1,
    padding: 10,
    backgroundColor:'rgba(255,255,255,0.8)',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center',
  }
})
const styles = StyleSheet.create({
  container: {
    backgroundColor: '#FFF'
  },
  flatlist: {

  },
})

3 个答案:

答案 0 :(得分:1)

javascript中的函数每次调用只能返回一个数据结构。将JSX语法中的每个元素都视为一个函数,因为这就是它们的本质。您需要返回一个元素(函数)或一个元素数组(一个函数数组)。在React 16之前,解决此错误的方法是将每组元素包装在div中。要么返回一个元素数组(但必须提供一个键)。如果您使用的是React16,则可以使用Fragment。他们看起来像这样。

import React, { Fragment } from 'react;

class Hello extends React.Component {

   render() {
       return (
           <Fragment>
               <h1>Hello</h1>
               <h2>World</h2>
           </Fragment>
       );
    }
}

这样,您就不必在不需要的DOM上添加额外的标记。

答案 1 :(得分:0)

React希望您以某种方式构造JSX。将<div>标记中的内容包装起来。

答案 2 :(得分:0)

错误基本上表明React希望将JSX元素包含在一个JSX元素中:div,span等。

但是,有几种方法可以达到期望的结果:

旧方法(反应15及以下-使用跨度):

<span>
  <Input 
    style={styles.field} 
    autoCorrect={false} 
    autoCapitalize="none" 
    placeholder="Skriv en kommentar..." 
  /> 
  <Button 
    rounded 
    style={styles.button} 
    onPress={() => props.addComment()}
  >
    <Text style={styles.buttonText}>Kommenter</Text> 
  </Button>
</span>

反应16岁以上(<Fragment> ... </Fragment>):

<Fragment>
  <Input 
    style={styles.field} 
    autoCorrect={false} 
    autoCapitalize="none" 
    placeholder="Skriv en kommentar..." 
  /> 
  <Button 
    rounded 
    style={styles.button} 
    onPress={() => props.addComment()}
  >
    <Text style={styles.buttonText}>Kommenter</Text> 
  </Button>
</Fragment>

反应16岁以上([ array with keys ]):

[ 
  <Input
    key="comment-input" 
    style={styles.field} 
    autoCorrect={false} 
    autoCapitalize="none" 
    placeholder="Skriv en kommentar..." 
  />, 
  <Button 
    rounded
    key="add-comment-button" 
    style={styles.button} 
    onPress={() => props.addComment()}
  >
    <Text style={styles.buttonText}>Kommenter</Text> 
  </Button>
]