I have a react app that I made in VS Studio, putting it into codepen, it doesnt seem to load a thing, any suggestions?
I have tried making sure React is linked and checked all of my syntax, no errors on local host but no display in codepen.
I have looked through the code multiple times and I feel its such a silly mistake
https://codepen.io/donnieberry97/pen/EzmOvW
class TodoListt extends React.Component {
state = {};
constructor(props) {
super(props);
this.state = {
userInput: "",
list: [],
editing: false,
};
}
changeUserInput(input) {
this.setState({
userInput: input
})
}
addToList() {
if (this.state.userInput === "") { (alert("Please enter a To-do")); return; };
const { list, userInput } = this.state;
this.setState({
list: [...list, {
text: userInput, key: Date.now(), done: false
}],
userInput: ''
})
}
handleChecked(e, index) {
console.log(e.target.checked);
const list = [...this.state.list];
list[index] = { ...list[index] };
list[index].done = e.target.checked;
this.setState({
list
})
}
handleEditing(e) {
this.setState({
editing: true
})
}
handleRemoved(index) {
const list = [...this.state.list];
list.splice(index, 1);
this.setState({
list
})
}
render() {
var viewStyle = {};
var editStyle = {};
if (this.state.editing) {
viewStyle.display = "none"
}
else {
editStyle.display = "none"
}
return (
<div className="to-do-list-main">
<input
onChange={(e) => this.changeUserInput(e.target.value)}
value={this.state.userInput}
type="text"
/>
<div class="submitButton">
<button onClick={() => { this.addToList(this.state.userInput) }}>Add todo</button>
</div>
{this.state.list.map((list, index) => (
<div className="form">
<ul>
{/* <div style={viewStyle} onDoubleClick={this.handleEditing.bind(t his)}> */}
<li key={list.key}>
<div class="liFlexCheck">
<input type="checkbox" onChange={(e) => this.handleChecked(e, index)} />
</div>
<div class="liFlexText">
<div class="liFlexTextContainer">
<span style={{ textDecoration: list.done ? 'line-through' : 'inherit' }}>
{list.text}
</span>
</div>
</div>
<button onClick={(index) => this.handleRemoved(index)}>Remove</button>
<input
type="text"
style={editStyle}
value={list.text}
/>
</li>
{/* </div> */}
</ul>
</div>
))}
</div>
);
}
}
Remove the import statements, working example.
You shouldn't use import when you got External Scripts.
Also, you got many errors in your code that should be handled, like:
<div class="submitButton">, use className.
Each child in a list should have a unique key prop.
Form field with value prop but without onChange handler.
Check out the logs:
In codpen, you don't need to import the react instead just write code,
here is codepen working one : codepen
from codesandbox, you can learn with all imports also because it doesn't uses any external scripts,
your code will work fine if you add an import to it
that is import ReactDOM from 'react-dom';
codesandbox will show all these suggestions,
here is codesandbox working example: codesandbox
Related
I am very new to programming and working on an MVP project for a FS app where I have a small database of books which I render through a .map. Currently, I am rendering the cover of all the books in my database and when I click on the cover it shows the title, author and summary. The functionality is working but it is looking rubbish as when I click any book it pushes everything around and I would like for it to show as a modal box above my list of books. This is my code below, do you have any idea how to achieve that? Thanks so much :)
import Filter from "./components/filter"
import './App.css';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
books:[],
showBook: []
};
}
componentDidMount() {
this.getBookclub();
}
getBookclub = () => {
fetch(`/books`)
.then(response => response.json())
.then(response => {
this.setState({ books: response });
});
};
handleClick(e){
for (let i = 0 ; i < this.state.books.length ; i++) {
this.state.showBook[i] = false;
}
let bookShow = [...this.state.showBook];
bookShow[e.target.name-1] = true;
this.setState({
showBook: bookShow
});
}
renderLibrary() {
return this.state.books.map((books,id) => {
return(
<li key={id} className="book-list">
<span onClick ={() => this.getBookclub(books.id)}>
<div>
**<img onClick={(e) => this.handleClick(e)} name={books.id} src={books.cover} alt={books.title}/>
</div>
<div className={this.state.showBook[books.id-1] ? "bookDetails" : "bookhidden"}>
<br/>
<div className="cover-book-show">
<h5>{books.title}</h5>
</div>
<div className="author-book-show">
<h6>{books.author}</h6>
</div>
<div className="summary-book-show">
<p>{books.summary}</p>
</div>**
</div>
</span>
</li>
)
})}
filterBook(filteredList){
this.setState({
books: filteredList
})
}
render() {
return (
<div>
<h1>Books</h1>
<div>
<Filter filterBook={filteredList => this.filterBook(filteredList)}/>
</div>
<br/>
<ul>
**<div className="all-books">
{this.renderLibrary()}
</div>**
</ul>
</div>
);
}
}```
googlemapapiI'm having issues fetching google map, it says the page can't load correctly, I also have some errors on my console. I don't understand what I'm doing wrong, I should be able to make a query and have the places showing in the suggestions, but I'm doing something wrong. here is my component, I have also attached a photo. All help will be welcome [
import React, { Component } from "react";
import { Map, Marker, GoogleApiWrapper } from "google-maps-react";
const apiKey = process.env.REACT_APP_GOOGLE_API_KEY;
const center = {
lat: 51.5074,
lng: 0.1278,
};
let service = null;
export class MapContainer extends Component {
constructor(props) {
super(props);
this.state = {
input: "",
suggestions: [],
places: [],
};
}
savePlace = (place) => {
this.setState({ places: [...this.state.places, place] });
};
handleChange = (e) => {
this.setState({ input: e.target.value });
};
handleKeyPress = (event) => {
if (event.key === "Enter") {
this.search();
}
};
search = () => {
const {input} = this.state;
service.textSearch({query: input}, (suggestions) => {
this.setState({suggestions});
})
};
initPlaces(mapProps, map) {
const { google } = mapProps;
service = new google.maps.places.PlacesService(map);
}
render() {
const { suggestions, places } = this.state;
return (
<div className="container">
<div className="row">
<div className="col">
<div className="form-inline d-flex justify-content-between mb-4">
<input
type="text"
value={this.state.input}
onChange={this.handleChange}
className="form-control flex-grow-1"
placeholder="Search for places on Google Maps"
onKeyPress={this.handleKeyPress}
/>
<button onClick={this.search} className="btn btn-primary ml-2">
Search
</button>
</div>
<h3>Suggestions</h3>
<ul className="list-group">
{suggestions.map((place, i) => (
<li
key={i}
className="list-group-item d-flex justify-content-between align-items-center"
>
<div>
<div>
<strong>{place.name}</strong>
</div>
<span className="text-muted">
{place.formatted_address}
</span>
</div>
<button
className="btn btn-outline-primary"
onClick={() => this.savePlace(place)}
>
Show
</button>
</li>
))}
</ul>
</div>
<div className="col">
<Map google={this.props.google} zoom={14} initialCenter={center} onReady={this.initPlaces}></Map>
</div>
</div>
</div>
);
}
}
export default GoogleApiWrapper({
apiKey,
})(MapContainer);
]2
I checked your code and if you directly put your API key in your
const apiKey = "PUT_YOUR_API_KEY_HERE"; , it will properly show your map.
It seems that you are putting your variables in the .env file (refer here on how to add custom environment variables). Make sure that you put your .env file outside the src folder and set this inside your .env file :
REACT_APP_GOOGLE_API_KEY=API_KEY_VALUE_HERE. This works for me.
You can find the sample code in this link.
Make sure to change the value of the REACT_APP_GOOGLE_API_KEY in the .env file to your API key.
Hope this helps!
Take a look on my Chat.js contents:
import React, { Component } from "react";
class Chat extends Component {
constructor(props) {
super(props);
this.state = {
messages: [],
message: ""
};
}
submitMessage(event) {
event.preventDefault();
this.setState(state => ({
messages: [<li>{this.state.message}</li>, ...state.messages]
}));
this.setState({
message: ""
});
}
render() {
return (
<>
<div class="container py-3">
<h2 className="text-center mb-4">Simple Chat</h2>
<form
onSubmit={e => {
this.submitMessage(e);
}}
>
<input
type="text"
className="form-control"
placeholder={"Enter your message..."}
value={this.state.message}
onChange={e => this.setState({ message: e.target.value })}
/>
<button type="submit" className="btn btn-success mt-2">
Send Message
</button>
</form>
<div className="container border mt-2">
<ul className="group-list mt-3 pt-2">{this.state.messages}</ul>
</div>
</div>
</>
);
}
}
export default Parent;
Also, this is my example:
https://codesandbox.io/s/objective-water-1e8uq
i need to replace user link when anyone type username with #
for example, this is my message content:
Are you good #Daniel ?
I need to convert above message to following content:
Are you good #Daniel ?
I use react-router-dom, so i need to replace link with this code:
Eg:
<Router>
<Link to={ '#'} onClick={() => {this.example()}}>
#Daniel
</Link>
</Router>;
It should be done with a string replace:
// This is to have as tag "Are you good #Daniel ?" (with # in the username)
const replacementReg = /(#[a-zA-Z0-9]+)/g;
// This is to have as tag "Are you good Daniel ?" (without # in the username)
const replacementReg = /#([a-zA-Z0-9]+)/g;
function decorateWithLink(text) {
text.replace(replacementReg, replaced => ` ${replaced} `);
}
and you should use in your component:
this.setState(state => ({
messages: [
<li>{decorateWithLink(this.state.message)}</li>,
...state.messages
],
message: '' // with this you don't need to call again the this.setState
}));
I have updated your submitMessage function here is the code:
submitMessage(event) {
event.preventDefault();
const { message } = this.state;
let msg = message.replace(/#([a-zA-Z0-9]+)/g, value => ` ${value} `);
this.setState(state => ({
messages: [<li dangerouslySetInnerHTML={{__html: msg}} />, ...state.messages]
}));
this.setState({
message: ""
});
}
here is the working code: https://codesandbox.io/s/stupefied-platform-zmg94
I am fetching data from an API to build a page that will display recipes as a fun little app to add on to my "things I've built" list. I can run the fetch call and see that the state is updated in dev tools, but after adding a ternary operation to render this new data once the search is performed, the new state/data does not seem to pass into my child component props.
I've tried providing default values to the recipes prop
recipes={ this.state.results || {"id": 1, title: "test", "servings": "6", "readyInMinutes": 10}}
and I've tried setting isLoading in the callback of my setState call
this.setState({ results: resData.data.results},
() => { this.setState({isLoading: false});} )
I've been all over stack overflow and other resources trying just about anything i can find...I understand the setState is asynchronous and I've tried playing around with every solution I can find on google rephrasing this question over and over, and at this point I assume its some precise problem that I am just not noticing.
Main Component:
class CookingPage extends Component {
state = {
results: [],
isLoading: true,
}
isActive = true;
constructor(props) {
super(props);
}
// componentDidMount(){
// this.setState({
// isLoading: false
// });
// }
srchApi = e => {
e.preventDefault();
let validated = false;
let query = document.getElementById('search').value;
let cuisine = document.getElementById('cuisine').value;
let diet = document.getElementById('diet').value;
if(query){
validated = true;
}
if (!validated) {
//code to notify user of invalid search
return;
} else {
fetch('http://localhost/cooking', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: query,
cuisine: cuisine,
diet: diet
})
}).then(res => {
return res.json();
}).then(resData => {
if(this.isActive){
debugger;
this.setState({
results: resData.data.results,
isLoading: false
});
}
}).catch(err => {
if(this.isActive){
this.setState({isLoading: false});
}
});
}
}
componentWillUnmount() {
this.isActive = false;
}
render() {
return (
<div className='background'>
<div className="container">
<div className="row">
<div className="col-12">
<div className='container search-ctr'>
<Form>
<div className='row'>
<div className='col-4 plain-search'>
<Form.Group controlId='search'>
<Form.Label>Plain Search</Form.Label>
<Form.Control type='text' placeholder='Recipes...Nutrients...Ingredients...Just search!'></Form.Control>
</Form.Group>
</div>
<div className='col-4 col-cuisine'>
<Form.Group controlId='cuisine'>
<Form.Label>Cuisine</Form.Label>
<Form.Control type='text' placeholder='Italian, Mexican, etc..'></Form.Control>
</Form.Group>
</div>
<div className='col-4 col-diet'>
<Form.Group controlId='diet'>
<Form.Label>Diet</Form.Label>
<Form.Control type='text' placeholder='Vegetarian, Vegan, etc...'></Form.Control>
</Form.Group>
</div>
</div>
<div className='row'>
<div className='col-12'>
<button type="submit" className="btn btn-outline-light btnSearch" onClick={this.srchApi}>Search</button>
</div>
</div>
</Form>
</div>
</div>
</div>
<div className='row'>
<div className='col-12'>
{this.state.isLoading ? (<div></div>) :
<RecipeList
recipes={this.state.results}
onDetail={this.showDetailsHandler}
/>
}
</div>
</div>
</div>
</div>
);
}
}
export default CookingPage;
Child component:
const RecipeList = props => {
const mapRecipes = props.recipes.map(recipe => {
return(
<PreviewRecipe
key = {recipe.id}
className = "preview-recipe"
recipekey = {recipe.id}
recipeid = {recipe.id}
title = {recipe.title}
cookTime = {recipe.readyInMinutes}
servings = {recipe.servings}
onDetail = {props.onViewDetail}
/>
)
});
return (
<React.Fragment>
<div className = "recipe-list-ctr">
<h4 className = "recipe-list-title">Title</h4>
<h4 className = "recipe-list-servings">Servings</h4>
<h4 className = "recipe-list-img">Image</h4>
</div>
{mapRecipes}
</React.Fragment>
)
};
export default RecipeList;
I expect a list of RecipeList components to display on the page after being mapped from the props, however I get the error:
"TypeError: Cannot read property 'map' of undefined.
As I explained before, using dev tools and removing the isLoading:false from the setState call, I can see in dev tools that the state is updating to the data received from the API, so I am really unsure as to why it is not being passed through. My understanding of the life-cycle just might not be up to par yet, and I would appreciate and solutions or suggestions to help me debug and get back on the right track.
I've figured out the issue I believe. After days and hours of debugging, the issue came to be that my import statement for one of my components was importing from the wrong file. Thus it was rendering a component with props that were undefined.
I'm trying to make simple CRUD example using react.js as frontend.
I already have add/edit functionality done in a component,
but I want to call this component dynamically on click and show it as a popup or modal window on the same page without redirecting to another route.
Does anyone have experience with doing this using react.js?
This is my parent component code where I show a grid of items displaying cities:
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, NavLink } from 'react-router-dom';
interface FetchNaseljeDataState {
nasList: NaseljeData[];
loading: boolean;
}
export class FetchNaselje extends React.Component<RouteComponentProps<{}>, FetchNaseljeDataState> {
constructor() {
super();
this.state = { nasList: [], loading: true };
fetch('api/Naselje/Index')
.then(response => response.json() as Promise<NaseljeData[]>)
.then(data => {
this.setState({ nasList: data, loading: false });
});
// This binding is necessary to make "this" work in the callback
this.handleDelete = this.handleDelete.bind(this);
this.handleEdit = this.handleEdit.bind(this);
}
public render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: this.renderNaseljeTable(this.state.nasList);
return <div>
<h1>Naselje Data</h1>
<p>This component demonstrates fetching Naselje data from the server.</p>
<p>
<Link to="/addnaselje">Create New</Link>
</p>
{contents}
</div>;
}
// Handle Delete request for an naselje
private handleDelete(id: number) {
if (!confirm("Do you want to delete naselje with Id: " + id))
return;
else {
fetch('api/Naselje/Delete/' + id, {
method: 'delete'
}).then(data => {
this.setState(
{
nasList: this.state.nasList.filter((rec) => {
return (rec.idnaselje != id);
})
});
});
}
}
private handleEdit(id: number) {
this.props.history.push("/naselje/edit/" + id);
}
// Returns the HTML table to the render() method.
private renderNaseljeTable(naseljeList: NaseljeData[]) {
return <table className='table'>
<thead>
<tr>
<th></th>
<th>ID Naselje</th>
<th>Naziv</th>
<th>Postanski Broj</th>
<th>Drzava</th>
</tr>
</thead>
<tbody>
{naseljeList.map(nas =>
<tr key={nas.idnaselje}>
<td></td>
<td>{nas.idnaselje}</td>
<td>{nas.naziv}</td>
<td>{nas.postanskiBroj}</td>
<td>{nas.drzava && nas.drzava.naziv}</td>
<td>
<a className="action" onClick={(id) => this.handleEdit(nas.idnaselje)}>Edit</a> |
<a className="action" onClick={(id) => this.handleDelete(nas.idnaselje)}>Delete</a>
</td>
</tr>
)}
</tbody>
</table>;
}
}
export class NaseljeData {
idnaselje: number = 0;
naziv: string = "";
postanskiBroj: string = "";
drzava: DrzavaData = { iddrzava: 0, naziv: ""};
drzavaid: number = 0;
}
export class DrzavaData {
iddrzava: number = 0;
naziv: string = "";
}
This is my child component that I want to dynamically show on create new link click:
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, NavLink } from 'react-router-dom';
import { NaseljeData } from './FetchNaselje';
import { DrzavaData } from './FetchNaselje';
interface AddNaseljeDataState {
title: string;
loading: boolean;
drzavaList: Array<any>;
nasData: NaseljeData;
drzavaId: number;
}
export class AddNaselje extends React.Component<RouteComponentProps<{}>, AddNaseljeDataState> {
constructor(props) {
super(props);
this.state = { title: "", loading: true, drzavaList: [], nasData: new NaseljeData, drzavaId: -1 };
fetch('api/Naselje/GetDrzavaList')
.then(response => response.json() as Promise<Array<any>>)
.then(data => {
this.setState({ drzavaList: data });
});
var nasid = this.props.match.params["nasid"];
// This will set state for Edit naselje
if (nasid > 0) {
fetch('api/Naselje/Details/' + nasid)
.then(response => response.json() as Promise<NaseljeData>)
.then(data => {
this.setState({ title: "Edit", loading: false, nasData: data });
});
}
// This will set state for Add naselje
else {
this.state = { title: "Create", loading: false, drzavaList: [], nasData: new NaseljeData, drzavaId: -1 };
}
// This binding is necessary to make "this" work in the callback
this.handleSave = this.handleSave.bind(this);
this.handleCancel = this.handleCancel.bind(this);
}
public render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: this.renderCreateForm(this.state.drzavaList);
return <div>
<h1>{this.state.title}</h1>
<h3>Naselje</h3>
<hr />
{contents}
</div>;
}
// This will handle the submit form event.
private handleSave(event) {
event.preventDefault();
const data = new FormData(event.target);
// PUT request for Edit naselje.
if (this.state.nasData.idnaselje) {
fetch('api/Naselje/Edit', {
method: 'PUT',
body: data,
}).then((response) => response.json())
.then((responseJson) => {
this.props.history.push("/fetchnaselje");
})
}
// POST request for Add naselje.
else {
fetch('api/Naselje/Create', {
method: 'POST',
body: data,
}).then((response) => response.json())
.then((responseJson) => {
this.props.history.push("/fetchnaselje");
})
}
}
// This will handle Cancel button click event.
private handleCancel(e) {
e.preventDefault();
this.props.history.push("/fetchnaselje");
}
// Returns the HTML Form to the render() method.
private renderCreateForm(drzavaList: Array<any>) {
return (
<form onSubmit={this.handleSave} >
<div className="form-group row" >
<input type="hidden" name="idnaselje" value={this.state.nasData.idnaselje} />
</div>
< div className="form-group row" >
<label className=" control-label col-md-12" htmlFor="Naziv">Naziv</label>
<div className="col-md-4">
<input className="form-control" type="text" name="naziv" defaultValue={this.state.nasData.naziv} required />
</div>
</div >
<div className="form-group row">
<label className="control-label col-md-12" htmlFor="PostanskiBroj" >Postanski broj</label>
<div className="col-md-4">
<input className="form-control" name="PostanskiBroj" defaultValue={this.state.nasData.postanskiBroj} required />
</div>
</div>
<div className="form-group row">
<label className="control-label col-md-12" htmlFor="Drzava">Država</label>
<div className="col-md-4">
<select className="form-control" data-val="true" name="drzavaid" defaultValue={this.state.nasData.drzava ? this.state.nasData.drzava.naziv : ""} required>
<option value="">-- Odaberite Državu --</option>
{drzavaList.map(drzava =>
<option key={drzava.iddrzava} value={drzava.iddrzava}>{drzava.naziv}</option>
)}
</select>
</div>
</div >
<div className="form-group">
<button type="submit" className="btn btn-default">Save</button>
<button className="btn" onClick={this.handleCancel}>Cancel</button>
</div >
</form >
)
}
}
I'm assuming I'll have to make css for the create/edit component to make it look like a popup...
EDIT: I would appreciate if someone could make code example using my classes, thanks...
In the parent component set a state on click functionality, say for eg:
this.setState({display: true})
In the parent component render based on condition display child component, say for eg:
<div>{(this.state.display) ? <div><childComponent /></div> : ''}</div>
To display the child component in a modal/popup, put the component inside say a bootstrap or react-responsive-modal. For that, you have to install and import react-responsive-modal and then
In the render method,
return (
<div>
{this.state.toggleModal ? <div className="container">
<Modal open={this.state.toggleModal} onClose={this.onCloseModal} center>
<div className="header">
<h4>{Title}</h4>
</div>
<div className="body">
<div>
{this.state.toggleModal ? <someComponent /> : ''}
</div>
</div>
</Modal>
</div>
: null}
</div>
)
Have your popup component receive a prop from the parent that will tell it if it should be displayed or not, a simple boolean will do the trick. Then, when you want something to show the popup, just change that state in the parent.