简体   繁体   中英

Fetching document as JSON using React-Native

I have found some similar solutions but not one that does exactly what I want.

Here is what I wanna do: I have a few documents saved as JSON in a server, I want to fetch those documents using React-Native and display them on my phone. However, think about a solution when I don't have to change my code every time I upload a new document to the server. React-native should be able to fetch everything from the server, even the new documents, without having to add new lines of code in the return{} . Those documents might differ from each other, some includes only text, some include text and input fields, some include pictures, text and input fields.

If something is unclear please let me know in the comment section. Any suggestion would be highly appreciated!

Example of JSON how it would look like:

    {  
   "results":[  
      {  

         "contract":{  
            "title":"Contract test",
            "content":"You can always follow the progress of your application by logging on the the application portal. Please note that all communication from DTU will take place via this portal. When we have sent you a message on the ..."
         },

        "fillable_fields": {
            "FIELD_NAME_1": "FIELD_VALUE_1",
            "FIELD_NAME_2": "FIELD_VALUE_2",
            "FIELD_NAME_N": "FIELD_VALUE_N"
        },
         "picture":{  
            "medium":"https://www.healthcaredenmark.dk/media/11272/bridgeit_logo.png"
         }
      }
   ]
}

My code in React-Native:

class HomeScreen extends React.Component {

  constructor() {

    super();
    this.state = {};
    this.getRemoteData();

  }


  static navigationOptions = {
    title: 'List of documents',
  };



  getRemoteData = () => {
    const url = "https://demo8106568.mockable.io/results";
    fetch(url)
      .then(res => res.json())
      .then(res => {
        this.setState({
          data: res.results
        });
      })
      .catch(error => {
        console.log("get data error from:" + url + " error:" + error);
      });
  };


  capFirstLetter = (string) => {
    return string.charAt(0).toUpperCase() + string.slice(1);
  }


  renderNativeItem = (item) => {
    const contract =
      this.capFirstLetter(item.contract.title);
      //this.capFirstLetter(item.name.content);

    return <ListItem
            roundAvatar
            title={contract}
            subtitle={item.content}
            avatar={{ uri: item.picture.thumbnail }}
            onPress={() => this.onPressItem(item)}
          />;
  }


     onPressItem = (item) => {
     this.props.navigation.navigate('Detail', {item: item})
   }


  render() {
    return (
      <View>
        <FlatList
          data={this.state.data}
          renderItem={({item}) => this.renderNativeItem(item)}
        />
        {/* <Button
          title="Go Detail"
          onPress={() => this.props.navigation.navigate('Detail', {source: "homescreen"})}
        /> */}
      </View>
    );
  }
}





class DetailScreen extends React.Component {


  static navigationOptions = {
    title: 'Content of selected'
  };


  render() {

    const source = this.props.navigation.state.params.source;
    const item = this.props.navigation.state.params.item;
    let contract = "";
    let img = "";
    let inp = "";
    let content ="";

    if (item != null) {
      contract = item.contract.title;
      img = item.picture.medium;
      content = item.contract.content;
      inp = item.fillable_fields.FIELD_NAME_1;
    }


    return (

      <View style={styles.container}>

        <Text style={styles.text}>{contract} </Text>

        <Image
          style={{width: 300, height: 128}}
          source={{uri: img}}
        />

        <Text  style={styles.text} > {content} </Text>

        <TextInput style={{textAlign: 'center', borderWidth:1, marginBottom: 7, height: 50}} source={{uri: inp}}/>        

        <Button title="Go back to the list" onPress={this._goHome}/>

      </View>

    );
  }


  _goHome = async () => {
    this.props.navigation.navigate('Home');
  };
}

I understand what you are trying to accomplish. But I really don't think you can make it work like you want. You can compare it to calling a normal API endpoint. You will most likely have a method like:

getContracts() {
    fetch('CONTRACTS_ENDPOINT').then(res => doSomethingWithContracts(res))
}

You already know that this data returns contracts and you already know what data to expect there. Therefore you can easy access fields like contract.name , or contract.date .

And when you want to call some other endpoint you will do something similar

getSomethingElse() {
    fetch('OTHER_ENPOINT').then(res => ...)
}

You will know the data that comes with the OTHER_ENPOINT , so you can directly access its fields.

So my suggestion is, think of each of you document as a separate API endpoint. Of course, if you change your document, you will also need to change client side implementation, so for example if you rename contract.title to contract.otherWordForTitle then you will obviously need to change that on the client as well.

From what I know, what you want, to have the client always know the document structure without updating it in order to know that a document has changed, is not possible. But of course, I might be wrong and there can be a workaround :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM