#javascript #react-native #axios #jsx
Вопрос:
Я делаю вызов axios в рендеринге моего родного приложения react.
render() {
return (
<View style={{flex: 1, backgroundColor: 'white'}}>
<ScrollView
style={styles.scrollView}
contentContainerStyle={{justifyContent: 'center'}}>
<Text style={styles.heading}>Checked Out Books</Text>
{this.state.books.map((book) => {
axios
.get('http://localhost:3000/books/id/' book)
.then((res) => {
console.log(res.data);
return (
<View>
<Image
source={{uri: res.data.cover}}
height={150}
width={110}></Image>
<Text>{res.data.title}</Text>
</View>
);
})
.catch((err) => {
console.log(err);
alert('Something went wrong.');
});
})}
Когда вызов завершается и он переходит к шагу возврата, ничего не возвращается.
Я не знаю, почему это происходит. Этот сегмент кода не возвращается:
<View>
<Image
source={{uri: res.data.cover}}
height={150}
width={110}></Image>
<Text>{res.data.title}</Text>
</View>
Почему это происходит?
Комментарии:
1. Ты ничего не вернешь в
map
2. О, как бы я это сделал? Извините, я новичок в родной реакции
Ответ №1:
В соответствии с комментарием , из которого вы ничего не возвращаете .map()
, функция стрелки либо не должна иметь скобок «нравится (book) => axios.get(
«, либо должна иметь скобки и использовать слово return
«нравится (book) => { return axios.get(
«.
return
Оператор, на который вы смотрите вместе с <View>
элементом, предназначен return
для функции .then()
обратного вызова, а не для всей .map()
функции.
Но это не решит вашу проблему , потому что значение, которое вы будете возвращать из .map()
, равно a Promise
, а это не то, что вы можете распечатать в своем компоненте JSX.
@jamielarchin прав в том, что вы не можете выполнять выборку данных внутри своего render()
метода. Это должно быть внутри метода жизненного componentDidMount
цикла, такого как componentDidUpdate
или внутри useEffect
крючка. Поскольку вы только учитесь, я рекомендую вам учиться с использованием самого современного подхода, который заключается в использовании функционального компонента и useEffect
.
Я рекомендую вам обрабатывать выборку данных для каждой книги в отдельном Book
компоненте, а не заниматься выборкой данных в цикле. Это намного проще, и это позволяет избежать необходимости переписывать весь список, если меняется только одна книга.
Вы можете сделать этот Book
компонент функциональным компонентом и сохранить текущий компонент «список книг» в качестве компонента класса.
// the book id is the only prop
const Book = ({ id }) => {
const [isError, setIsError] = useState(false);
const [isLoading, setIsLoading] = useState(false);
// save the book data here, once loaded
const [data, setData] = useState();
useEffect(
() => {
setIsLoading(true);
axios
.get('http://localhost:3000/books/id/' id)
.then((res) => setData(res.data))
.catch((err) => setIsError(true))
.finally(() => setIsLoading(false));
},
[id] // dependency on the book id
);
if (data !== undefined) {
return (
<View>
<Image source={{ uri: data.cover }} height={150} width={110}></Image>
<Text>{data.title}</Text>
)}
</View>
);
}
// can show loading and error components too
// but for now I'm just returning nothing
return null;
};
render() {
return (
<View style={{flex: 1, backgroundColor: 'white'}}>
<ScrollView
style={styles.scrollView}
contentContainerStyle={{justifyContent: 'center'}}>
<Text style={styles.heading}>Checked Out Books</Text>
{this.state.books.map((book) => <Book id={book} key={book}/>)}
Ответ №2:
Извлечение данных должно выполняться методом жизненного цикла для компонентов класса. Вероятно, вы хотите использовать componentDidMount: https://reactjs.org/docs/react-component.html#componentdidmount
Ответ №3:
Вы не должны вызывать axios внутри рендеринга (это возможно с некоторыми корректировками, однако это не очень хорошая практика). Вы должны либо использовать крючки (например, useEffect), если вы находитесь в функциональном компоненте, либо использовать componentDidMount, если вы находитесь в компоненте класса (как я предполагаю). Примеры приведены ниже.
class App extends React.Component {
constructor(){
this.state = {
bookIds: [], //You would fill this beforehand
books: [],
}
}
componentDidMount(){
for(let i = 0; i < bookIds; i ){
axios.get('http://localhost:3000/books/id/' bookIds[i]).then((res) => {
books.push(res);
}.catch((err) => {
console.log(err);
alert('Something went wrong.');
});
}
}
render() {
return(
<View style={{flex: 1, backgroundColor: 'white'}}>
<ScrollView
style={styles.scrollView}
contentContainerStyle={{justifyContent: 'center'}}>
<Text style={styles.heading}>Checked Out Books</Text>
{this.state.books.map((book) => {
return (
<View>
<Image
source={{uri: book.data.cover}}
height={150}
width={110}>
</Image>
<Text>{book.data.title}</Text>
</View>
);
})
}
);
}
}
Я бы рекомендовал вам взглянуть на это: https://reactjs.org/docs/state-and-lifecycle.html.
Возможно, возникнут какие-то проблемы с скобками, Хорошего дня!