Проблемы с попыткой вернуть данные api без класса
Я построил api, который возвращает мне единицы, которые я зарегистрировал в БД, но при попытке вернуть их не просматривают
import React, { Component } from 'react';
import axios from 'axios';
const api = {
units: () => {
axios.get('http://192.168.0.23/api/public/api/units')
.then(response => {
console.log(response);
return response.data.data
}).catch((error) => {
console.log(error.message)
});
return 'Error'
},
};
export default api;
Ответ отображает данные правильно, response.data.data
, если он используется в файле с классом I, можно установить состояние units = []
и с setState
вернуть единицы
Однако я хотел бы создать этот файл для возвратов api, однако, поскольку я не использую класс, поэтому понимаю, что я не могу использовать состояние.
Есть ли способ без класса, возвращающего эти данные, или сохранения в переменной или что-то в этом роде?
Или используйте setState
прямо здесь без класса?
Я считаю, что это будут способы решения моей проблемы, но если кто-то другой знает иначе, чем положить api-вызов в тот же файл, что и последний класс.
Я тоже пробовал:
async function getUnits() {
return await axios.get('http://192.168.0.23/api/public/api/units');
}
getUnits.then((response) => {
console.log(response);
return response.data.data
}).catch((response) => {
console.log(response)
});
Но ошибка показала, что getUnits.then is not a function
Даже с нормальной функцией не работает:
function units() {
axios.get('http://192.168.0.23/api/public/api/units')
.then(response => {
console.log(response);
return response.data.data
}).catch((error) => {
console.log(error.message)
});
return 'Error'
};
Ответы
Ответ 1
Используйте следующий код, это поможет вам.
Обычно мы просто загружаем данные, а затем выводим наше приложение. Но React ожидает некоторого начального состояния для всех этих данных и нуждается в обновлении сразу после завершения запроса AJAX. По этой причине вам нужно сохранить все эти данные в состоянии приложения.
Вот как это выглядит:
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import axios from 'axios';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {units: []};
}
componentDidMount() {
this.getUnits();
}
getUnits() {
axios.get('http://192.168.0.23/api/public/api/units')
.then(response => {
this.setState({ units: response.data.data }));
}).catch((error) => {
console.log(error.message)
});
}
render() {
const unit = this.state.units.map((item, i) => (
<div>
<h1>{ item.example }</h1>
</div>
));
return (
<View style={{ flexGrow: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Units: {unit}</Text>
</View>
);
}
}
И если вы хотите, чтобы субкомпоненты передавали эти данные до. Вот что это выглядит:
const unit = this.state.units.map((item, i) => (
<div>
<h1>{ item.example }</h1>
<Test unitData={item} />
</div>
));
В другом компоненте Test
class Test extends Component { //use the data in a class component
constructor(props) {
super(props);
}
render() {
const unit = this.props.unitData
return (
<div className="test">
<h1>{unit.example}</h1>
</div>
);
}
}
Пожалуйста, посмотрите пример здесь, который поможет вам решить вашу проблему.
Примеры:
Надеюсь, это поможет вам!
Ответ 2
Сначала в этом фрагменте
async function getUnits() {
return await axios.get('http://192.168.0.23/api/public/api/units');
}
getUnits.then((response) => {
console.log(response);
return response.data.data
}).catch((response) => {
console.log(response)
});
Вы допустили ошибку, вы должны вызвать функцию getUnits
здесь, например:
getUnits().then(.....)
Относительно того, использовать или не использовать компонент с состоянием или функциональный компонент, просмотрите документацию здесь для некоторого объяснения различий.
На первой странице обсуждаются функциональные компоненты, которые не управляют своим собственным состоянием. вторая страница обсуждает состояние.
В вашей ситуации один из компонентов должен будет выполнить вызов AJAX, поэтому один компонент должен отвечать за состояние. Если вы используете Redux, разговор становится совсем другим. Однако, если вы не используете Redux, вы, как правило, будете иметь состояние в компоненте с высоким уровнем состояния с компонентами без состояния под ним. Базовый компонент передаст данные (из вашего запроса AJAX) своим детям без гражданства с помощью реквизита (которые доступны только для чтения).
Итак, наконец, мы сможем получить код! В вашем объекте api
позвольте поддерживать способ передачи данных обратно вызывающему абоненту. Здесь мы добавляем параметры обратного вызова onLoad
и onError
, которые принимают функции как аргументы.
Когда приходит успешный ответ, обратный вызов onLoad
вызывается с данными из API. При возникновении ошибки обратный вызов onError
вызывается с сообщением об ошибке.
import axios from 'axios';
const api = {
units: (onLoad, onError) => {
axios.get('http://192.168.0.23/api/public/api/units')
.then(response => {
onLoad(response.data.data);
}).catch((error) => {
onError(error.message);
});
},
};
export default api;
Теперь мы сделаем ваш компонент App
stateful (помните, он может иметь детей без гражданства, чтобы он передавал данные через реквизит). Обратите внимание, что мы вызываем вызов API прямо перед тем, как компонент будет монтироваться, потому что мы вызываем его в componentWillMount
метод жизненного цикла React. Это не помешает рендерингу компонента, поскольку, поскольку ваш объект api
выполняет асинхронный вызов, он просто вызывает запрос API и немедленно отображает ваш компонент. Как только данные поступят, ваш объект api
вызовет обратный вызов onLoad
, который является методом onApiLoad
вашего компонента App
. Компонент App
затем обновит свое состояние и повторную визуализацию!
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import api from './units';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {units: []};
}
componentWillMount() {
api.units(this.onApiLoad, this.onApiError);
}
onApiLoad(units) {
this.setState({
units: units
});
}
onApiError(errorMessage) {
// TODO Something meaningful with error message
}
render() {
const unit = this.state.units.map((item, i) => (
<div>
<h1>{ item.example }</h1>
</div>
));
return (
<View style={{ flexGrow: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Units: {unit}</Text>
</View>
);
}
}
Ответ 3
Если у меня возникла ваша проблема, то это то, что вам нужно сделать:
измените это:
import React, { Component } from 'react';
import axios from 'axios';
const api = {
units: () => {
axios.get('http://192.168.0.23/api/public/api/units')
.then(response => {
console.log(response);
return response.data.data
}).catch((error) => {
console.log(error.message)
});
return 'Error'
},
};
export default api;
в
import axios from 'axios';
const api = {
units: () => {
return axios.get('http://192.168.0.23/api/public/api/units')
.then(response => {
console.log(response);
return response.data.data
}).catch((error) => {
console.log(error.message)
});
return 'Error'
},
};
export default api;
просто добавил оператор возврата перед axios
затем используйте его в своем компоненте, например
import api from './api';
....
....
....
componentDidMount() {
api.units().then(units => this.setState({ units }))
}
....
....
....
Ответ 4
Я столкнулся с этой проблемой асинхронного обратного вызова в мои первые дни программирования с помощью javascript, где мне было очень сложно передавать результаты между файлами с использованием чистых функций. Я могу предложить вам что-то, что вы можете использовать в любом месте с асинхронным программированием в javascript и не имеет никакого отношения к response.js
import React, { Component } from 'react';
import axios from 'axios';
const api = {
units: (callback) => {
axios.get('http://192.168.0.23/api/public/api/units')
.then(response => {
console.log(response);
callback(response.data.data);
}).catch((error) => {
console.log(error.message)
});
return 'Error'
},
};
export default api;
И внутри вашего компонента App
:
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
import api from './units';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
units: [],
};
}
//Always do async tasks(side effects) in componentDidMount, I will provide you a link to know Do and Dont with lifecycle hooks.
componentDidMount() {
if(this.state.units.length === 0){
api.units((data) => this.setState({units: data}));
}
}
render() {
return (
<View style={{ flexGrow: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Units: {this.state.units}</Text>
</View>
);
}
}
Это способ передачи функций обратного вызова, когда вы работаете с асинхронными операциями в Javascript, так как вы не можете вернуть результат evaluated
из функции async, потому что, как только результат все еще будет оцениваться, ваша функция будет return
что-то и выйти из scope
, но вы можете использовать обработчик callback
операции async, чтобы, наконец, обновить ваше представление в соответствии с оцененным result
. Я обрабатываю только обратный вызов success
, вы можете передать обратный вызов error
, чтобы обработать случай ошибки.