When I call my API via my web browser I get the following result:
{"statusCode": 200, "body": "\"Cheers from AWS Lambda!\""}
However, I am now struggeling to show body via axios. Do you see what I am doing wrong?
import axios from "axios";
import React, { Component } from "react";
class App extends Component {
state = {
messages: []
};
componentDidMount() {
axios
.get(
"https://12345.execute-api.eu-central-1.amazonaws.com/prod/get-data"
)
.then(response => {
const messages = response.data;
this.setState({ messages });
});
}
render() {
return (
<ul>
{this.messages}
Test
{this.state.messages.map(message => (
<li>{message}</li>
))}
</ul>
);
}
}
export default App;
A few points:
1) Change this.messages in ul of render method to this.state.messages, as this.messages is undefined.
2) A good practice while using JSX is to keep js and html code as distinguishable as possible, so the map on a list should be done outside the return statement.
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
3) For more info about CORS error and how to rectify it while using AWS lambda, refer to this article which includes a code snippet: AWS: CORS
Related
I tried to create an application from an Random user API in react and I used axios library for HTTP Requests.I created a separate file for base API using axios.create and the file code goes as,
import axios from 'axios'
export default axios.create({
baseURL: `http://jsonplaceholder.typicode.com`,
});
Then I used this in another file to make an GET request and store the data in state on componentdidMount so ill can access the data in UI.
import React from "react";
import API from "../api";
export default class PersonList extends React.Component {
state = {
persons: []
};
componentDidMount() {
API
.get('/').then((data) => {
const persons = data.data;
this.setState({ persons });
console.log(this.state.persons);
});
}
render() {
const { persons } = this.state;
console.log('Stato',persons)
return (
<ul>
{persons.map((person) => (
<li key={person.id}>{person.name}</li>
))}
</ul>
);
}
}
But it doesn't work ,because the state is not filled up with Users data,so the .map() function is throwing an error.
You're encountering this error because of the URL you are using. In your example, you use https://jsonplaceholder.typicode.com as the endpoint in componentDidMount, but that isn't going to return any placeholder user data. I believe you meant to use https://jsonplaceholder.typicode.com/users instead.
I have a working example here: https://codesandbox.io/s/axios-instance-ki9g6. Notice how I only had to change / in componentDidMount to /users.
I am building a site just like stackoverflow.com. I want my home page to display top questions. For that, I have sample questions on the backed. Now, I want to display only the question and tags from the questions array.
The code is in the image
I have made axios connection for that:
const instance = axios.create({
baseURL: "https://2w2knta9ag.execute-api.ap-south-1.amazonaws.com/dev", });
instance.defaults.headers.post["Content-Type"] = "application/json";
To connect it, I wrote the command: instance.get("/questions)
Now, how do I display only the question and tags??
EDIT:
On using the code given bellow, my js file now becomes:
import React from 'react';
import instance from '../../api';
class QuestionList extends React {
componentDidMount() {
instance
.get("/questions")
.then((res) => {
this.setState({ data: res.data });
});
}
render () {
const { data } = this.state;
return <div>
{
data && data.map(d => {
return <div>question: {d.question}, tags: {d.tags}</div>;
})
}
</div>
}
}
export default QuestionList;
But, this is just making my site in a loading state, and it gets hanged!!
If I understood correctly, you want to get an array only with the tags and the question. if so, you can use Array.prototype.map for this
const questions = result.map(({ question, tags }) => ({ question, tags }))
First you export the axios instance so that it can be used from other components.
Now you can send the api request in componentDidMount and update your component's state with the data.
And in render function, you just get the value from state and display.
If you are new to react, learn React Hooks and know that componentDidMount method is the best place to send api requests.
For Example:
import React from 'react';
import instance from '../../api';
class QuestionList extends React.Component {
constructor() {
super();
this.state = {
data: [],
};
}
componentDidMount() {
instance.get('/questions').then((res) => {
this.setState({ data: res.data });
});
}
render() {
const { data } = this.state;
return (
<div>
{data &&
data.map((d) => {
return (
<div>
question: {d.question}, tags: {d.tags}
</div>
);
})}
</div>
);
}
}
export default QuestionList;
I got this code:
import React from 'react'
import fetch from 'isomorphic-unfetch'
import Layout from '../../src/components/layout'
import Nav from '../../src/components/nav'
import Fluid from '../../src/components/fluid'
Post.getInitialProps = async ({ query }) => {
const res = await fetch(`https://schoolvol.mdcholewka.now.sh/api/getPost?slug=${query.slug}`)
const json = await res.json()
return json
}
function Post({ post }) {
return (
<Layout>
<Nav />
<Fluid>
{post ? <p>{post.id}</p> : <p>Ładowanie...</p>}
</Fluid>
</Layout>
)
}
export default Post
The problem is, when I load the site it returns "Ładowanie..." (which means loading in Polish). After a while, nobody happens. What's the solution?
I took a look at this sample: https://nextjs.org/learn/basics/fetching-data-for-pages/fetching-batman-shows. Instead of doing return json, I believe that you have to use return { post: json }.
Nevermind, I just remove these {} out of function's arguments and it's now working fine.
I was trying to host my React project on GH Pages. The deploy worked fine but when I try to search for gifs I get the following error
http_browser.js:47 Mixed Content: The page at
'https://pimmesz.github.io/react-giphy/' was loaded over HTTPS, but
requested an insecure XMLHttpRequest endpoint
'http://api.giphy.com/v1/gifs/search?
q=h&limit=10&rating=g&api_key=MYAPIKEY'. This request has been blocked; the
content must be served over HTTPS.
It seems like the Giphy API is making a http request instead of https. Is there a way to change the default url which the API uses?
import React, { Component } from 'react';
import giphy from 'giphy-api';
import Search from './search.jsx';
import Gif from './gif.jsx';
import GifList from './gif_list.jsx';
class App extends Component {
constructor(props) {
super(props);
this.state = {
gifs: [],
gif: "xBoysJgwhLEZtAjbY1"
}
}
search = (query) => {
giphy('APIKEY').search({
q: query,
limit: 10,
rating: 'g'
}, (err, res) => {
this.setState({gifs: res.data})
});
}
select = (id) => {
this.setState({gif: id})
}
render() {
const gifs = this.state.gifs;
return (
<div>
<div className="left-scene">
<Search search={this.search}/>
<Gif id={this.state.gif} select={this.select} />
</div>
<div className="right-scene">
<GifList gifs={gifs} select={this.select} />
</div>
</div>
);
}
}
export default App;
Changed the giphy API execution to
const url = `https://api.giphy.com/v1/gifs/search?q=${query}&limit=10&rating=g&api_key=MY_API_KEY`
fetch(url)
.then(results => { return results.json();
}).then(data => {
this.setState({gifs: data.data});
});
EDIT
Found another way!
Setting https to true can be done as an option in the giphy api call
giphy({ apiKey: "MY_API_KEY", https: true })
I'm using slack API to retrieve messages from bot app (like trello in slack.com). I used this API https://slack.com/api/im.history. But my goal, is to get messages from that bot app in real time to my application without reloading page. I already read the RTM API docs, and also The events API. I didn't figure out how to do so. What should I do ?
Here is server/main.js :
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';
import '../imports/api/messages.js';
Meteor.startup(() => {
Meteor.methods({
checkSlack() {
this.unblock();
try {
var result = HTTP.call('GET','https://slack.com/api/im.history', {
params: {
token: 'xxxx-xxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx',
channel: 'xxxxxxxxxx'
}
});
return result.data.messages;
} catch (error) {
// Got a network error, timeout, or HTTP error in the 400 or 500 range.
return error.message;
}
}
});
});
imports/api/messages.js:
import { Mongo } from 'meteor/mongo';
export const Messages = new Mongo.Collection('messages');
if (Meteor.isServer) {
// This code only runs on the server
Meteor.publish('messages', function messagesPublication() {
return Messages.find();
});
}
imports/ui/Message.jsx:
import React, { Component, PropTypes } from 'react';
export default class Message extends Component {
render() {
return (
<li>{this.props.message.text}</li>
);
}
}
Message.propTypes = {
message: PropTypes.object.isRequired,
};
imports/ui/App.jsx:
import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { Messages } from '../api/messages.js';
import Message from './Message.jsx';
const _ = require('lodash');
// App component - represents the whole app
class App extends Component {
constructor(props){
super(props);
this.state = {
messages: [],
};
this.renderMessages = this.renderMessages.bind(this);
this.getMessages = this.getMessages.bind(this);
this.saveMessages = this.saveMessages.bind(this);
}
componentDidMount() {
this.getMessages();
}
getMessages() {
const handle = this;
Meteor.call('checkSlack',function(err, response) {
if(err){
console.log('error');
}
else {
handle.setState({
messages: response,
});
}
});
};
renderMessages() {
const messages = Messages.find({}).fetch();
return messages.map((message, index) => (
<Message key={index} message={message} />
));
}
saveMessages(){
const messages = this.state.messages;
const msgs = Messages.find({}).fetch();
var addedMsgs = _.differenceBy(messages,msgs, 'ts');
_.map(addedMsgs, (message) =>
Messages.insert(message)
);
}
render() {
return (
<div className="container">
<header>
<h1>Messages List</h1>
</header>
<button onClick={this.saveMessages}>Save</button>
{this.renderMessages()}
</div>
);
}
}
App.propTypes = {
messages: PropTypes.array.isRequired,
};
export default createContainer(() => {
Meteor.subscribe('messages');
return {
messages: Messages.find({}).fetch(),
};
}, App);
client/main.jsx:
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import App from '../imports/ui/App.jsx';
Meteor.startup(() => {
render(<App />, document.getElementById('render-target'));
});
client/main.html:
<head>
<title>App</title>
</head>
<body>
<div id="render-target"></div>
</body>
If you can get the Slack events coming through from the API, to a Meteor server, simply insert them into a Mongo collection, and then set up your Meteor client to subscribe to the database, and you will have a real time feed to your UI
UPDATE
Thanks for possting your code, now I can see what's going on.
1) In your server code you are doing this:
Meteor.startup(() => {
Meteor.methods({
It probably works OK, but these are independent things. Meteor methods often lives in another file, and is just used to declare your methods.
2) You only save the messages to the collection from the UI. They need to be inserted when you get them in the server method - then your publication and subscription will work
3) Remove the call to checkSlack from componentDidMount, and put it in the server startup.
4) Your http request to slack will only retrieve the history, you need to get more sophisticated here. Read https://api.slack.com/rtm for how you can open a socket and get a real time feed