How to pull images from Airtable Database? - reactjs

When I try to compile my code, I get the error:
Error Image
I was following a tutorial and the only difference is the name of each column/field in Airtable. My project should be working but it isn't. Did I forget to declare something in particular? Is there an easier way to get images from Airtable? React Airtable Tutorial
import React, { Component } from 'react';
import { Container, Row, Col, Card, CardImg, CardText, CardBody,
CardTitle, CardSubtitle, Button } from 'reactstrap';
import './main.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
skills: [],
};
}
componentDidMount() {
fetch('https://api.airtable.com/v0/appXy4JgrvUicfB5F/Resources?api_key=keyE0exOkvaAnJeS0')
.then((resp) => resp.json())
.then(data => {
console.log(data);
this.setState({ skills: data.records });
}).catch(err => {
// Error 🙁
});
}
render() {
return (
<div className="container">
<Row>
<Col>
{this.state.skills.map(skill => <Roster {...skill.fields} /> )}
</Col>
</Row>
</div>
);
}
}
export default App;
const Roster = ({ Name, Service, LinkedIN, GitHub, Twitter, Facebook, Picture }) => (
<div className="card">
<div className="card-body">
<img className="card-img-left" src={Picture[0].url} />
<h5 className="card-title">{Name}</h5>
<p className="card-subtitle">{Service}</p>
<p className="card-text">
<small className="text-muted"></i></small>
<small className="text-muted"></i></small>
<small className="text-muted"></i></small>
<small className="text-muted"></i></small>
</p>
</div>
</div>
);

The Airtable API that you are using does not have a Picture property in for lots of objects and they are failing when trying to access Picture[0] because Picture is undefined.
If you do not have images for all objects, the easy way would be check if there is a Picture first before rendering:
{Picture && <img className="card-img-left" src={Picture[0].url} />}
Demo on Stackblitz

Related

Fetching and displaying data with React

i am new to react and have been trying this for a long time without any success. Maybe someone could look through and determine the mistate i am making. here is my code.
I have the App.js file with a route to services page where i want to fecth and display data divs with services from a mysql database with react and JSX.
import React, { Component } from "react";
import { BrowserRouter } from "react-router-dom";
import Footer from "./Footer";
import Header from "./Header";
import axios from "axios";
class Services extends React.Component {
constructor(props) {
super(props);
this.state = {
services: [],
};
}
componentDidMount() {
axios
.get("http://localhost:5000/services")
.then((response) => this.setState({ services: response.data }));
}
render() {
var { services } = this.state;
return (
<div>
<div className="row">
<BrowserRouter>
<Header></Header>
</BrowserRouter>
<div className="Services">
<br></br>
<br></br>
<br></br>
</div>
<div className="row">
<h1 className="text-center title">Our Services</h1>
<p className="p-3 text-left">
Quickly get help for your issue by selcting the service that
matches your issues. You can always describe your issue if it does
not match any of our services and you only pay when the issue has
been resolved.
</p>
<hr></hr>
{services}
</div>
</div>
<BrowserRouter>
<Footer></Footer>
</BrowserRouter>
</div>
);
}
}
export default Services;
import React from "react";
import { BrowserRouter } from "react-router-dom";
import axios from "axios";
class Services extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
axios.get("https://jsonplaceholder.typicode.com/posts").then(response => {
console.log(response);
this.setState({ data: response.data });
});
}
render() {
let services_data = [];
this.state.data.forEach((res, i) => {
services_data.push(
<ul key={res.i}>
<li>{res.id}</li>
<li>{res.title}</li>
<li>{res.body}</li>
</ul>
);
});
return (
<div>
<div className="row">
<BrowserRouter>Header</BrowserRouter>
<div className="Services" />
<div className="row">
<h1 className="text-center title">Our Services</h1>
<p className="p-3 text-left">
Quickly get help for your issue by selcting the service that
matches your issues. You can always describe your issue if it does
not match any of our services and you only pay when the issue has
been resolved.
</p>
<hr />
{services_data}
</div>
</div>
<BrowserRouter>Footer</BrowserRouter>
</div>
);
}
}
export default Services;
The above code is working fine and split the method like this.

SPFx React FileViewer for Sharepoint Custom List

I am new to SPFx and React. The requirement is to read a Sharepoint Custom List and render the list columns with custom look and feel. This is achieved and read all the attachments (more than one, for a single list item).
How to open all the attachments with React FileViewer (more than one) in browser?
public render(): React.ReactElement<ICirDetailsProps> {
this._renderListAsync();
return(
<div className="${ styles.cirDetails }">
<div className="${ styles.container }">Circulars<br/>
<div id="cirDetails" className="${ styles.details}"></div>
</div>
</div>
);
}
attachments.forEach((afile: any) => {
let fileUrl = hostURL + afile.ServerRelativeUrl;
let fileExt = this.getFileExtension(afile.ServerRelativeUrl);
attFiles += `<FileViewer fileType='${fileExt}' filePath='${afile.ServerRelativeUrl}' /><br/>`;
});
const listContainer: Element = document.querySelector("#cirDetails") as HTMLElement;
listContainer.innerHTML=html;
It shows no error, but the attachments are not opened within browser. I could see the React FileViewer tags are rendered as HTML Content using F12. What is the mistake am I doing here?
Sample demo:
import * as React from 'react';
import styles from './MyReactFileViewer.module.scss';
import { IMyReactFileViewerProps } from './IMyReactFileViewerProps';
import { escape } from '#microsoft/sp-lodash-subset';
import FileViewer from 'react-file-viewer';
import * as CSS from 'csstype';
import { sp } from "#pnp/sp";
import { IAttachmentInfo } from "#pnp/sp/attachments";
import { IItem } from "#pnp/sp/items/types";
import "#pnp/sp/webs";
import "#pnp/sp/lists/web";
import "#pnp/sp/items";
import "#pnp/sp/attachments";
interface IPnpstate {
attachments: any[]
}
export default class MyReactFileViewer extends React.Component<IMyReactFileViewerProps, IPnpstate> {
constructor(props: IMyReactFileViewerProps, state: IPnpstate) {
super(props);
this.state = {
attachments: []
};
}
public componentDidMount() {
let item = sp.web.lists.getByTitle("MyList").items.getById(18);
// get all the attachments
item.attachmentFiles.get().then((files:IAttachmentInfo[]) => {
var attachs=[];
files.map(file=>{
var fileType=file.FileName.split('.').pop();
var fileUrl=file.ServerRelativeUrl;
attachs.push({"fileType":fileType,"fileUrl":fileUrl});
})
console.log(attachs);
this.setState({attachments:attachs});
});
}
public render(): React.ReactElement<IMyReactFileViewerProps> {
return (
<div className={styles.myReactFileViewer}>
<div className={styles.container}>
<div className={styles.row}>
<div className={styles.column}>
<span className={styles.title}>Welcome to SharePoint!</span>
<p className={styles.subTitle}>Customize SharePoint experiences using Web Parts.</p>
<p className={styles.description}>{escape(this.props.description)}</p>
<a href="https://aka.ms/spfx" className={styles.button}>
<span className={styles.label}>Learn more</span>
</a>
{(this.state.attachments || []).map((item, index) => (
<div key={item.ID}>
<FileViewer
fileType={item.fileType}
filePath={item.fileUrl}
/>
</div>
))}
</div>
</div>
</div>
</div>
);
}
}
I used IFrame tag, based on the file types, the iframe renders differently.

react how to make a pagination in external api

Please need help paginating the results of information in an external API (pokeapi.co) I can fetch all the items, I have limited the answers to one hundred units and now I want to page ten out of ten per page but have the following error , when I click pagination links to switch pages and the items still don't appear as paginated.
Please, can anyone help me? Thank you in advance.
import React, { Component } from 'react';
import axios from 'axios';
import Pagination from 'react-js-pagination';
import PokemonCard from './PokemonCard';
require ('bootstrap-less/bootstrap/bootstrap.less');
export default class PolemonList extends Component {
constructor(props) {
super(props);
this.state = {
activePage: 1,
pageNumber: 10
};
}
handlePageChange(pageNumber) {
console.log(`active page is ${pageNumber}`);
this.setState({activePage: pageNumber});
}
state = {
url: 'https://pokeapi.co/api/v2/pokemon/?offset=0&limit=100',
pokemon: null
};
async componentDidMount() {
const res = await axios.get('https://pokeapi.co/api/v2/pokemon/?offset=0&limit=100');
this.setState({ pokemon: res.data['results'] })
}
render() {
return(
<React.Fragment>
{this.state.pokemon ? (
<div className="row">
{this.state.pokemon.map(pokemon => (
<PokemonCard
key={pokemon.name}
name={pokemon.name}
url={pokemon.url}
/>
))}
</div>
) : (
<h2>Loading Pokemon</h2>
)}
<hr></hr>
<div className="row">
<div className="col-12 text-center">
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={8}
totalItemsCount={100}
pageRangeDisplayed={10}
onChange={this.handlePageChange}
/>
</div>
</div>
</React.Fragment>
);
}
}
Error below:
this.setState is not a function in line 21 of the code that I list.
Your code is valid, so there must be an error with your build/project setup or some other issue.

Packery draggable in React Component

I am building a product grid order tool for an e-commerce website. It allows the merchandiser to change the order in which the products display.
This is achieved through drag-and-drop superpowers of Packery by David Desandro https://packery.metafizzy.co/
Seems there are two ways to do this. Either run his code (with jQuery) in a componentDidMount() {}; or find a React version of Packery, like https://www.npmjs.com/package/react-packery-component . There are a number of these but all present a similar problem. Their examples call the object differently. (Mine has curly braces). And I am getting a frightening TypeError!
TypeError: Cannot read property 'bool' of undefined
import React, { Component } from 'react'
import {
Card,
CardImg,
CardBody,
CardTitle,
Input,
InputGroup,
Container,
Row,
// Col,
Jumbotron
} from 'reactstrap';
import Papa from 'papaparse'
import 'bootstrap/dist/css/bootstrap.min.css'
import './App.css'
import Packery from 'react-packery-component'
class App extends Component {
constructor(props) {
super(props);
this.state = {data: [] }; // State holds gridorder / neworder
this.handleChange = this.handleChange.bind(this);
this.updateData = this.updateData.bind(this)
}
handleChange(event) {
event.preventDefault()
const inventory = event.target.files[0]
Papa.parse(inventory, {
header: true,
complete: this.updateData
})
} // END
updateData(results) {
const data = results.data
console.log(data)
this.setState({data}) // {data:data}
}
renderData() {
return this.state.data.length > 1
? this.state.data.map((item) => ( // Object in return
<Card className="grid-item" key={item.sku} >
<CardImg src={item.image} />
<CardTitle> {item.sku} </CardTitle>
<CardBody> {item.name} </CardBody>
</Card>
))
: null
}
render() {
return (
<div>
<Jumbotron>
<form >
<InputGroup>
Name:
<Input type="file" onChange={this.handleChange} />
</InputGroup>
</form>
</Jumbotron>
<div className="album">
<Container>
{/* This throws a TypeError. NOTE: I am calling renderData() */}
<Packery className="grid" > {this.renderData()} </Packery>
</Container>
</div>
</div>
);
}
} // END
export default App
The reason I am keeping the object in state is because, that is the thing that will change. gridorder in, neworder out. Thank you in advance, for I could sure use the help.

React API elements not displaying on page

I've been looking for about 2 hours into why I am not displaying any of the information to the page. I've console logged my response from a simple random quote api and it shows, Author: and Quote: in the console, however these are not appearing in my fields, All I am seeing is the button.
import React, { Component } from 'react';
import QuoteMachine from './Quotemachine';
const END_POINT = 'https://random-quote-
generator.herokuapp.com/api/quotes/random';
class App extends Component {
constructor(props) {
super(props);
this.state = {
quote: {
text: '',
author: ''
}
}
}
getQuote() {
fetch(END_POINT)
.then(response => response.json())
.then(response => {
this.setState = ({
quote: response
});
console.log(response);
})
}
componentDidMount() {
this.getQuote();
}
render() {
return (
<div className="App">
<div className="container">
<QuoteMachine quote= {this.state.quote} />
<button id="new-quote" className="primary-color-
background" onClick={() => this.getQuote()}>New quote</button>
</div>
</div>
);
}
}
export default App;
And then here is my Quotemachine.js
import React from 'react'
import PropTypes from 'prop-types';
const QuoteMachine = (props) => {
return (
<div className="quote-box">
<div className="text">
<span>{props.quote.text}</span>
</div>
<div className="author">
<span >{props.quote.author}</span>
</div>
</div>
);
};
QuoteMachine.propTypes = {
quote: PropTypes.object.isRequired
};
export default QuoteMachine;
It is only displaying the button, but the console.log shows
Object
author:
"Thomas Henry Huxley (1825-1895)"
quote:
"Try to learn something about everything and everything about something."
proto
:
Object
Install React Developer Tools plugin and check if your state is changing after the API call

Resources