问题
Sorry for the joke in the title.
I am currently exploring the fetch API in react native, but I have bumped in to some issues which I cannot wrap my head around.
So, I am trying to get a message from a server, which I am calling with the fetch API in the following manner:
var serverCommunicator = {
test: function() {
fetch(baseUrl , {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then((response) => response.text())
.then((responseText) => {
return (JSON.stringify(responseText));
})
.catch((error) => {
console.warn(error);
}).done();
},
module.exports = serverCommunicator;
When I tested using only console.log(responseText) my log gave me the correct message. However, now when I wanna try to put the content in the code as a message in a View it does not return as expected. Calling it in the following manner:
import Method from '../Services/Methods';
.
.
.
<View style={styles.card}>
<CardView
message={Method.test()}
/>
I can see how the function test is called properly when calling it like this, but for some reason, it does not write the message.
回答1:
This is a classic async issue, where your then function returns after render has already been called, with nowhere to return to.
Most common solution: display empty state message / loading indicator and fetch your server info when your component mounts. When your promise returns and then callback is fired, set the component state which will trigger a re-render, with your expected value.
class extends React Component
class YourComponent extends Component {
constructor() {
super()
this.state.text = 'Loading, please wait!' // default text
}
componentDidMount() {
fetch(baseUrl, options)
.then((response) => response.text())
.then((responseText) => {
this.setState({ text: responseText }) // this triggers a re-render!
})
}
render() {
return (
<View style={styles.card}>
<CardView
message={this.state.text} // <-- will change when fetch call returns
/>
</View>
)
}
}
React.createClass
var YourComponent = React.createClass({
getInitialState() {
return { text: 'Loading, please wait!' }
}, // <-- comma between functions, because object keys
componentDidMount() {
fetch(baseUrl, options)
.then((response) => response.text())
.then((responseText) => {
this.setState({ text: responseText }) // this triggers a re-render!
})
},
render() { /* ..same as above.. */ }
})
If you want to keep your current architecture where the fetch call is in the service, you need to return the initial call to fetch, which will return a promise. Then you can hook up then in your constructor:
var serverCommunicator = {
test: function() {
return fetch(baseUrl, options) // return a promise! ..important!
.then((response) => response.text())
.then((responseText) => {
return responseText
})
}
}
Then your imported function will return a promise..
import Method from '../Services/Methods'
...
componentDidMount() {
Method.test().then(responseText => {
this.setState({ text: responseText })
})
]
....
Hope that clears things up a bit about how promises work, and how to capture async data using state in React!
来源:https://stackoverflow.com/questions/37035423/react-native-fetch-api-not-returning-my-calls