What's up some guys... I'm having trouble displaying my data, which I fetch from my django modules. Fetching the data seems to work fine, however it won't render and display. Would very much appreciate any help. Right now only the containers and stuff is getting displayed, none of the data from the module. Here is my react component:
NewsItemPage.js
import "bootstrap/dist/css/bootstrap.min.css";
import React, {Component, useEffect, useState} from "react";
import {useParams} from "react-router-dom";
import {Card, Col, Container, Row} from "react-bootstrap";
import sheet from "./Images/metal-sheet.jpg";
import "./css/newsItem.css";
import {BoxArrowUpRight, Textarea} from "react-bootstrap-icons";
import {Link} from "react-router-dom";
function withParams(NewsItemPage){
return props => <NewsItemPage {...props} params={useParams()}/>
}
class NewsItemPage extends Component{
state={
item: {},
loading: true
}
async componentDidMount(){
let {id} = this.props.params;
try {
const res = await fetch(`http://localhost:8000/api/news/${id}`);
const item = await res.json();
this.setState({
item: item,
loading: false
})
}catch(e){
console.log(e);
}
}
render() {
if(this.state.loading){
return <h1 className="text-center">Vänligen vänta...</h1>
}
console.log(this.state.item);
return(
this.state.item ?
<Container fluid className="news-wrapper ">
<Row fluid className="news-page-col">
<Col className="news-page-col text-center mt-5 mb-5">
<h1>{this.state.item.title}</h1>
<hr className="divider"/>
</Col>
</Row>
<Row fluid className="gap-5 justify-content-center mt-5">
<Col>
<img src={this.state.item.image} alt="image"/>
</Col>
</Row>
<h4>{this.state.item.date}</h4>
<Row>
<Col>
<Textarea>{this.state.item.description}</Textarea>
</Col>
</Row>
</Container>
: <h1>Här finns inget ännu...</h1>
);
}
}
export default withParams(NewsItemPage);
And here is the output from the 'console.log(this.state.item);' inside the render method above:
0
:
created_on
:
"2023-01-18T16:01:15.744999Z"
description
:
"hello this is my testing news"
id
:
10
image
:
"http://localhost:8000/Images/Images/shutterstock_634808618-1-1024x683.png"
title
:
"testing"
[[Prototype]]
:
Object
length
:
1
[[Prototype]]
:
Array(0)
Related
I´m trying to update the Detail component data whenever I select a card component.
I´m using useContext hook but I´m stuck at this point and I don´t know how to do this.
Could anybody please help?.
enter image description here
context.js
import { createContext, useContext, useEffect, useState } from "react";
import api from "./api/players"
const APIcontext = createContext();
export function Provider({children}){
const [players, setPlayers] = useState([]);
const [currentPlayer, setCurrentPlayer] = useState(null)
useEffect(() => {
const fetchPlayers = async () => {
try{
const response = await api.get('/players');
setPlayers(response.data)
}
catch(err){
if(err.response){
console.log(err.response.data)
}else{
console.log(`Error: ${err.message}`)
}
}
}
fetchPlayers()
},[])
const UpdateDetails = () =>{
}
return(
<APIcontext.Provider value={{players, currentPlayer,UpdateDetails}}>{children}</APIcontext.Provider>
)
}
export default APIcontext;
This is the Detail Component where I want to display the data, whenever a card is selected on click.
Details.jsx
import React from "react";
import Button from "react-bootstrap/Button";
import Card from "react-bootstrap/Card";
import {useContext} from "react";
import APIcontext from "../context";
function Details() {
const {players} = useContext(APIcontext)
return (
<Card style={{width:"80%", marginRight:"20px"}}>
<Card.Header className="text-center"><h1>Details</h1>
</Card.Header>
<Card.Body className="px-5">
<h4>{players.realName}</h4>
<h4>{players.realName}</h4>
<h4>{players.assets}</h4>
<Button variant="primary">Go somewhere</Button>
</Card.Body>
</Card>
);
}
export default Details;
This is the Card component that displays the data from the players. By clicking on one of them the Details component should be updated.
Card Component
[enter code here
import React, { useEffect, useState, useContext } from "react";
import Card from "react-bootstrap/Card";
import APIcontext from "../context";
function Cards({}) {
const { players } = useContext(APIcontext);
console.log("players", players);
const { UpdateDetails} = useContext(APIcontext)
return (
<>
{players &&
players.map((player) => (
<Card
key={player.id}
className="mt-4 mx-2"
style={{
display: "flex",
width: "12rem",
height: "9rem",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
<Card.Body onClick={UpdateDetails}>
<Card.Title>{player.realName}</Card.Title>
<Card.Subtitle className="mb-2 text-muted">
{player.playerName}
</Card.Subtitle>
<Card.Text>{player.asset}</Card.Text>
</Card.Body>
</Card>
))}
</>
);
}
export default Cards;][2]
App.js
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
import Card from "./components/Card";
import Details from "./components/Details";
import { Container, Row, Col } from "react-bootstrap";
import Controls from "./components/Controls";
import { useEffect, useState } from "react";
import { Provider } from "./context";
function App() {
return (
<div className="App">
<Provider>
<Container className="p-3 d-flex flex-row justify-content-between">
<Container className="p-5 d-flex flex-row mb-4 bg-light rounded-3">
<Details />
<Controls />
</Container>
</Container>
<Container className=" mr-5 mb-4 bg-light rounded-3 " style={{width:"65%", float:"left", marginLeft:"10%"}}>
<Container className="d-flex flex-row flex-justify-content-center flex-wrap mr-5 mb-4 bg-light rounded-3" >
<Card className="mr-2"/>
</Container>
</Container>
</Provider>
</div>
);
}
export default App;
Context implementation is easy, you only need to understand its flow and how to update the root values.
You have done everything right, and I believe all that is left is for you to update the Details component on click of the Card component. Here's how you could go about it.
In the Card component, where you've handled the onClick event:
<Card.Body onClick={UpdateDetails}>, change it to: <Card.Body onClick={() => UpdateDetails(player)}>
This will help us send the data of the card we want to show in the Details component.
Inside the context file, in the UpdateDetails method, collect the argument passed while calling the function and set the currentPlayer accordingly like this:
const UpdateDetails = (player) => setCurrentPlayer(player)
Here, the context will get updated and wherever you use the currentPlayer value will receive the new data.
You also need the currentPlayer state inside Details file, import it along with players state:
const {players, currentPlayer} = useContext(ApiContext)
Now you can use currentPlayer.name or any other key from the player object.
Hope this helps. Please accept this answer if it does! Thank you!
I am quite new to React so I have a simple question I think. I am trying to take the weather description from the API and according to that, I am trying to show different images. I wrote a function getForecast and response.data.weather[0].description turns the right value. So according to that, I am assigning 'image' to different SVG's but in doesnt turn right.
import React, { useState } from 'react';
import axios from 'axios';
import './Products.css';
import ProductItem from './ProductItem';
import Weather from './Weather';
import { Container, Row, Col } from 'react-bootstrap';
function Products() {
const [imageTemp, setImage] = useState('images/umbrella.svg');
const getForecast = () => {
axios({
method: "GET",
url: 'http://api.openweathermap.org/data/2.5/weather?q=Kaunas&appid=7e6e14c967d752abbafb23a1f251b21c'
})
.then((response) => {
console.log(response.data.weather[0].description);
if (response.data.weather[0].description === "overcast clouds") {
setImage('images/umbrella.svg');
}
else if (response.data.weather[0].description === "clear") {
setImage('images/sunglasses.svg');
}
else {
setImage('images/snowflake.svg');
}
})
.catch((error) => {
console.log(error);
});
};
return (
<div className='products'>
<Container className="products-container">
<h2 className="products__title">Products</h2>
<h6 className="products__subtitle">Offers Today</h6>
<Row>
<Col xs="12" md="6" lg="6">
<Weather
src={imageTemp}
path='/'
/>
</Col>
<Col xs="12" md="6" lg="6">
<ProductItem
src='images/img-2.jpg'
text='The Best Coffee'
path='/'
/>
<ProductItem
src='images/img-3.jpg'
text='Top 100 Books'
path='/'
/>
</Col>
</Row>
</Container>
</div>
);
}
export default Products;
And here is my Weather component:
import React from 'react';
function Weather(props) {
return (
<div className='banner__item'>
<figure className='banner__item__pic-wrap'>
<img
className='banner__item__img'
src={props.src}
/>
</figure>
</div>
);
}
export default Weather;
I think there's not a call for getForecast anywhere.
If you wanna know how to call the function at the time you want, i'll recommend you to look into useEffect hook in detail.
You must use useEffect to call this method(getForecast)... Add this part to your code
useEffect(() => {
getForecast();
}, [imageTemp]);
I have a child functional component 'Display'. Which contains two buttons. The buttons toggle a state between true or false.
I want to pass this boolean value back to the parent container (component).
I then want to pass this boolean value to another child functional component called 'DisplayTitle'. Based on the boolean value I want to just update a string prop that gets rendered in the functional component.
I am slightly new to this. Should I be using redux or is there a more simple way of doing this? Thanks
Haven't yet
'Display' child component:
import * as React from 'react';
import Button from 'react-bootstrap/Button';
import Col from 'react-bootstrap/col';
interface Props {
buttonOneLabel: string;
buttonTwoLabel: string;
}
const Display = ({
buttonOneLabel,
buttonTwoLabel,
}: Props) => {
const [state, setVariant] = React.useState({ status: true });
return (
<>
<Col md="auto">
<Button
onClick={() => setVariant({ status: true })}
variant={state.status ? 'primary' : 'outline-primary'}
>
{buttonOneLabel}
</Button>
<Button
onClick={() => setVariant({ status: false })}
variant={state.status ? 'outline-primary' : 'primary'}
>
{buttonTwoLabel}
</Button>
</Col>
</>
);
};
export default Display;
'DisplayTitles' child component:
import * as React from 'react';
import Col from 'react-bootstrap/col';
interface Props {
title: string;
}
const DisplayTitles = ({
title,
}: Props) => (
<>
<Col>
<h3>{title}</h3>
</Col>
</>
);
export default DisplayTitles;
Parent component
import * as React from 'react';
import Jumbotron from 'react-bootstrap/Jumbotron';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/row';
import Title from './Title';
import SearchBy from './SearchBy';
import QuickSearch from './QuickSearch';
import Dates from './Dates';
import Display from './Display';
import DisplayTitle from './DisplayTitle';
import RunReport from './RunReport';
import AdvancedSearch from './AdvancedSearch';
import Options from './Options';
const Header = () => (
<div className="daily-sales-header">
<Jumbotron>
<Container fluid>
<Title
title="Daily Sales"
subTitle="(Single Page)"
/>
<Row>
<SearchBy
colClass="search-by-col"
buttonId="search-by-button"
buttonLabel="Search by"
/>
<QuickSearch
buttonLabel="Quick Search"
eleClass="quick-search"
eleIdBtn="quick-search-button"
/>
<Dates
fromClass="from-date"
fromLabel="From"
toClass="to-date"
toLabel="To"
/>
<Display
buttonOneLabel="Department"
buttonTwoLabel="Sub-Department"
onSelectLanguage={handleVari}
/>
<RunReport
buttonLabel="Run Report"
/>
</Row>
<Row>
<AdvancedSearch
buttonClass="adv-search-btn pull-right"
buttonLabel="Advanced Search"
/>
</Row>
</Container>
</Jumbotron>
<Row>
<DisplayTitle
title="Department Sales"
/>
<Options />
</Row>
</div>
);
export default Header;
Lifting state up is the most simple approach here.
Parent component will hold state for all children components and pass
1. Values as props
2. Callbacks so children may change values
Example (not tested, use as hint only)
const Header = () => {
const [state, setVariant] = React.useState({ status: true });
return <div className="daily-sales-header">
/* ... */
<Display
uttonOneLabel="Department"
buttonTwoLabel="Sub-Department"
onSelectLanguage={handleVari}
setVariant={setVariant.bind(this)}
status={state.status}
/>
/* ... */
<DisplayTitle
title="Department Sales"
status={state.status}
/>
<Options />
</Row>
</div>
}
Disply component will be
import * as React from 'react';
import Button from 'react-bootstrap/Button';
import Col from 'react-bootstrap/col';
interface Props {
buttonOneLabel: string;
buttonTwoLabel: string;
status: boolean;
setVariant: (status: {status: boolean}) => void;
}
const Display = ({
buttonOneLabel,
buttonTwoLabel,
status,
setVariant
}: Props) => {
return (
<>
<Col md="auto">
<Button
onClick={setVariant.bind(this, { status: true })}
variant={status ? 'primary' : 'outline-primary'}
>
{buttonOneLabel}
</Button>
<Button
onClick={setVariant.bind(this, { status: false })}
variant={status ? 'outline-primary' : 'primary'}
>
{buttonTwoLabel}
</Button>
</Col>
</>
);
};
export default Display;
Display titles will be
// ...
interface Props {
title: string;
status: boolean;
}
const DisplayTitles = ({
title,
status
}: Props) => (
<>
<Col>
<h3>{title}</h3>
<h3>{status}</h3>
</Col>
</>
);
// ...
As a result, when you click button in Display component, setVariant from parent component will be called. It updates status in parent which will be immedeately propagated as props to both Display and DisplayTitles
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.
I'm working on a small project that allows user to upload image and then the image will be displayed on a canvas.
I'm using react-konva for this.
I have a container component called DesignPage, which manages the state and pass event handlers to its children.
Inside this DesignPage component, I have 2 other components: Tools - Canvas
When I upload an image using Tools component, the image should be displayed on Canvas component.
I'm using react-dropzone inside Tools component to handle file upload
Inside this Canvas component, there is a child component called DesignImage, which is just for displaying the image.
But the thing is, it just doesn't change the image on canvas when I upload.
How can I fix that?
Here is my code:
DesignPage component:
import React, {Component} from 'react';
import {
Row,
Col
} from 'reactstrap';
import Tools from "../components/DesignPage/Tools";
import Canvas from "../components/DesignPage/Canvas";
import Styles from "../components/DesignPage/Styles";
class DesignPage extends Component {
state = {
text: '',
image: '',
files: []
};
static propTypes = {};
handleTextChange = e => {
this.setState({text: e.target.value});
};
handleFileDrop = files => {
this.setState({
files,
image: files[0].preview
});
};
render() {
return <Row>
<Col xs={12} md={4}>
<Tools
files={this.state.files}
onTextChange={this.handleTextChange}
onFileDrop={this.handleFileDrop}/>
</Col>
<Col xs={12} md={5}>
<Canvas
text={this.state.text}
image={this.state.image}/>
</Col>
<Col xs={12} md={3}>
<Styles/>
</Col>
</Row>;
}
}
export default DesignPage;
Tools component:
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
TabContent,
TabPane,
Nav,
NavItem,
NavLink,
Row,
Col,
FormGroup,
Label
} from 'reactstrap';
import classnames from 'classnames';
import Dropzone from 'react-dropzone';
class Tools extends Component {
state = {
activeTab: '1'
};
toggle = (tab) => {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
});
}
};
render() {
return <Row>
<Col xs={12}>
<div>
<Nav tabs justified>
<NavItem>
<NavLink
className={classnames({active: this.state.activeTab === '1'})}
onClick={() => {
this.toggle('1');
}}
>
Text
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({active: this.state.activeTab === '2'})}
onClick={() => {
this.toggle('2');
}}
>
Art
</NavLink>
</NavItem>
</Nav>
<TabContent activeTab={this.state.activeTab}>
<TabPane tabId="1">
<Row>
<Col sm="12">
<FormGroup>
<Label for={"custom-text"}>Enter text below</Label>
<textarea
className={"form-control"}
id={"custom-text"}
onChange={this.props.onTextChange}/>
</FormGroup>
<FormGroup>
<Label for={"font-select"}>Choose a font</Label>
</FormGroup>
</Col>
</Row>
</TabPane>
<TabPane tabId="2">
<Row>
<Col sm="12">
<FormGroup>
<div className="dropzone-container">
<Dropzone onDrop={this.props.onFileDrop}>
<p>Drop a design here, or click to select design to upload.</p>
</Dropzone>
</div>
</FormGroup>
</Col>
</Row>
</TabPane>
</TabContent>
</div>
</Col>
</Row>;
}
}
Tools.propTypes = {
files: PropTypes.array.isRequired,
onTextChange: PropTypes.func.isRequired,
onFileDrop: PropTypes.func.isRequired
};
export default Tools;
Canvas component:
import React from 'react';
import PropTypes from 'prop-types';
import {
Row,
Col
} from 'reactstrap';
import {Stage, Layer} from 'react-konva';
import UserText from "./Canvas/UserText";
import DesignImage from "./Canvas/DesignImage";
const Canvas = props => {
return <Row>
<Col xs={12} className={"canvas-container"}>
<div className={"object-container"}>
<img className={"object-img"} src={"images/iPhone5A.png"} alt={"iPhone5A"}/>
<div className="drawing-area">
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<UserText text={props.text}/>
<DesignImage image={props.image}/>
</Layer>
</Stage>
</div>
</div>
</Col>
</Row>;
};
Canvas.propTypes = {
text: PropTypes.string.isRequired,
image: PropTypes.string.isRequired
};
export default Canvas;
DesignImage component:
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Image} from 'react-konva';
class DesignImage extends Component {
state = {
image: null
};
static propTypes = {
image: PropTypes.string.isRequired
};
componentDidMount() {
const image = new window.Image();
image.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRYTULZCGUVEQJEXt9iB8PU4Kb2FMS9Z6ufR1FnQTdrEl5uBOl52Q';
image.onload = () => {
// setState will redraw layer
// because "image" property is changed
this.setState({
image: image
});
};
}
render() {
return <Image image={this.props.image} draggable={true}/>;
}
}
export default DesignImage;
You need write a code to update the image when the component has a new image from props.
class DesignImage extends Component {
state = {
image: null
};
static propTypes = {
image: PropTypes.string.isRequired
};
componentDidMount() {
this.updateImage();
}
componentDidUpdate() {
this.updateImage();
}
updateImage() {
const image = new window.Image();
image.src = this.props.image;
image.onload = () => {
this.setState({
image: image
});
};
}
render() {
return <Image image={this.state.image} draggable={true}/>;
}
}
Update:
You can use use-image hook for simpler image loading:
import useImage from 'use-image';
const DesignImage = ({ image }) => {
const imgElement = useImage(image);
return <Image image={imgElement} draggable={true}/>;
}