How ReactJS display fetch response onClick - javascript

I am trying to generate a random user information when pressing the button, and display the information above the button. In ProfilePanel.js, I created a avatar and user constants, which will use to show the information. In index.js, the avatar constant works for that since it doesn't need to use the Button. however, for user constant, it doesn't work. In below's code, I am fetching a api data to display user name, but it didn't show anything, I am not sure where wrong, is something wrong in Button.js or index.js. and how can I fix it. Can somebody help me out? Thanks.
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
index.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import Panel from "./ProfilePanel";
import axios from 'axios';
import './index.css';
import Button from './Button';
const url = 'https://randomuser.me/api/';
class App extends Component {
constructor(props) {
super(props);
this.state = {
contacts: []
}
}
componentDidMount() {
this.fetchdata();
}
fetchdata() {
axios.get(url)
.then(res => {
console.log(res);
this.setState({ contacts: res.data.results});
});
}
render(){
const {contacts} = this.state;
return (
<div className="panel">
{contacts.map(contact => (
<div class="panel">
<Panel
key={contact.picture} avatar={contact.picture.medium}
/>
<li class="flex-container">
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
<Button title="location" onClick={this.fetchdata}>
</Button>
<Button key={contact.email} title="email">
</Button>
<Button key={contact.phone} title="phone">
</Button>
<Button key={contact.login.password} title="password">
</Button>
</li>
</div>
))}
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById("root")
);
ProfilePanel.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import './index.css';
import Button from './Button';
const style={
borderRadius: 150,
margin: 15,
}
class Panel extends Component {
render() {
const { avatar, user } = this.props;
return (
<div className="Panel">
<div class="panels">
<div className="avatar">
<img src={avatar} class="imageStyle" alt="" width={"200%"} height={"auto"}/>
</div>
</div>
<div class="center">
<h2 className="user">{user}</h2>
</div>
</div>
);
}
}
export default Panel;
Button.js
import './index.css';
import React, { Component } from 'react';
class Button extends Component {
constructor(props) {
super(props);
this.state = {
open:false,
};
}
render() {
const { title } = this.props;
const {open} = this.state;
return (
<button className={` ${open ? 'open' : ''}`}
class='button' onClick={(e) => this.handleClick(e)}>
<div className="panel-heading">
<h2 class='buttoncenter'>{title}</h2>
</div>
</button>
);
}
handleClick(e) {
e.preventDefault();
this.setState({
open: this.state.open
})
}
}
export default Button;

You're not changing state in the handle click. You need to set open to true;
handleClick(e) {
e.preventDefault();
this.setState({
open: true
})
}

You need to pass your user information in index.js. I think you have missed to pass the user props to the panel component, so that it shows the avatar alone. Without passing the users props, you are trying to destructure there in panel component.
//index.js should be like this
render(){
const {contacts} = this.state;
return (
<div className="panel">
{contacts.map(contact => (
<div class="panel">
<Panel
key={contact.picture} user={contact.name} avatar={contact.picture.medium}
/>
<li class="flex-container">
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
<Button title="location" onClick={this.fetchdata}>
</Button>
<Button key={contact.email} title="email">
</Button>
<Button key={contact.phone} title="phone">
</Button>
<Button key={contact.login.password} title="password">
</Button>
</li>
</div>
))}
</div>
);
}

Related

Deleting multiple items in checkboxes at once using REACT

I'm trying to delete multiple items at once for checkboxes in REACT, but the code does not seem to delete the items being checked.
Here's my approach to doing this. I made a function in tasks.jsx file
called add_ids_to_be_deleted to append the id that was being checked
in the checkbox to an array of ids to be deleted called list_of_ids.
This function is called in the child component in priorityLists.jsx.
When the user clicks the delete button, I created a useEffect to
filter out all the items in toDo whose ids are not included in the ids
to be deleted.
The problem is it keeps deleting the last item whenever I check a checkbox regardless of the order.
For example, I add 3 checkboxes and
check the first checkbox to delete it. Instead of the first checkbox
being deleted, the last item is deleted even though it wasn't being
checked.
tasks.jsx
import React, { useState, useEffect } from 'react';
import { Delete, Refresh, Add } from '../components/Actions';
import { Header } from '../components/Header';
import ToDoList from '../components/TaskList';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faPlus, faTrash } from '#fortawesome/free-solid-svg-icons';
import { v4 as uuidv4 } from 'uuid';
function Task() {
const [toDo, setToDo] = useState([]);
const [idsToRefresh, setIdsToRefresh] = useState([]);
const [list_of_Ids, setIds] = useState([]);
const [filter_now, setFilterNow] = useState(false);
function addToDos() {
const id = uuidv4();
setToDo(
toDo.concat({
_isKey: id,
_checked: false,
value: <ToDoList _onDelete={add_Ids_ToBe_Deleted} _key={id} />
})
);
setIdsToRefresh(idsToRefresh.concat(id));
}
function switchNow() {
if (!filter_now) {
setFilterNow(true);
} else {
setFilterNow(false);
}
}
useEffect(() => {
if (toDo[0] !== undefined) {
setToDo(
toDo.filter(item => {
return !list_of_Ids.includes(item._isKey);
})
);
}
}, [filter_now]);
function add_Ids_ToBe_Deleted(_id_ToBe_Deleted) {
setIds(item => [...item, _id_ToBe_Deleted]);
}
function refresh() {
setToDo(
toDo.filter(item => {
return !idsToRefresh.includes(item._isKey);
})
);
}
return (
<div className="main-content">
<div className="container-fluid">
<div className="row underline">
<div className="col">
<div className="row">
<div className="col-3 pt-2">
<Refresh _refresh={refresh} />
</div>
<div className="col-6 text-center">
<Header header={'Tasks'} />
</div>
<div className="col-3 pt-2">
<button className="float-right">
<FontAwesomeIcon
onClick={switchNow}
icon={faTrash}
size="2x"
/>
</button>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col">
{toDo.map(item => {
return (
<div>
<ul>
<li>{item.value}</li>
</ul>
</div>
);
})}
</div>
</div>
<div className="row">
<div className="col pr-4">
<button onClick={addToDos} className="float-right" name="add">
<FontAwesomeIcon icon={faPlus} size="2x" />
</button>
</div>
</div>
</div>
</div>
);
}
export default Task;
Tasklist.jsx
import React from 'react';
import { PriorityLists } from '../components/PriorityLists';
import { Priority } from './Actions';
function ToDoList(props) {
return (
<PriorityLists
_onDelete={props._onDelete}
keys={props._key}
name="toDoList"
>
<Priority />
</PriorityLists>
);
}
export default ToDoList;
Prioritylists.jsx
import React, { useState, useEffect } from 'react';
import { Priority } from './Actions';
function PriorityLists(props) {
return (
<form>
<div className="input-group mb-3">
<div className="input-group-prepend">
<div className="input-group-text">
<input
is_checked={false}
unique_Key={props.keys}
onClick={e =>
props._onDelete(
e.target.attributes.getNamedItem('unique_Key').value
)
}
id="check-item"
type="checkbox"
aria-label="Checkbox for following text input"
/>
</div>
</div>
<textarea class="form-control" rows="1" name={props.name}></textarea>
{props.children}
</div>
</form>
);
}
export { PriorityLists };

how to display whats up in a responsive way by using react js

enter image description herei develop what's up web by using react. my scenario is when ever i execute in desktop it will be displayed in a desktop responsive and whenever i displayed in a mobile it will be displayed in a mobile responsive how to do that in react.
Below i can add each and every page i develop for displaying what's up web.i want to display in mobile like what's up app so how to develop.click the enter description here it will show the image i developed.but i need only one app to have both responsivness & web.that means one url i want whats web & mobile whats app.
ChatListHeader.js
import React, { Component } from 'react';
class ChatListHeader extends Component {
render(){
return(
<div className="chatlist--header">
<div className="chatlist--header__image">
<img src={require('/home/srinath/Desktop/important/whats up web ui complete/whats up web
ui/src/images/Srinath.png')} alt={""}/>
</div>
<div className="chatlist--header__icons">
<i className="material-icons"></i>
<i className="material-icons"></i>
</div>
</div>
)
}
}
export default ChatListHeader;
import React, { Component } from 'react';
import ChatListHeader from '../presentational/ChatListHeader';
import ChatListSearch from './ChatListSearch';
import List from './List';
class ChatList extends Component {
render(){
return(
<div className="chatlist">
<ChatListHeader />
<ChatListSearch />
<List contacts={this.props.contacts} getChats={this.props.getChats}/>
</div>
)
}
}
export default ChatList;
import React, { Component } from 'react';
class ChatListSearch extends Component {
render(){
return(
<div className="chatlist--search" style={{"position": "relative"}}>
<input type="" placeholder="search or start a new chat"/>
<img src={require('../../images/searchicon.png')} alt={""} style={{"width": "15px", "position":"absolute","bottom":"18px","left":"20px","fontSize":"15px"}} />
</div>
)
}
}
export default ChatListSearch;
import React, { Component } from 'react';
import ListItem from '../presentational/ListItem';
class List extends Component {
render(){
let listitem = this.props.contacts.map((item) => {
return <ListItem item={item} key={item.id} getChats={ this.props.getChats }/>
})
return(
<div className="list">
{listitem}
</div>
)
}
}
export default List;
import React, { Component } from "react";
class ListItem extends Component {
render(){
let item = this.props.item;
return (
<div className="list--item" onClick={ (event) => { this.props.getChats(event, item.id) } }>
<div className="list--item__image">
<img src={item.profilePhoto} alt={item.name}/>
</div>
<div className="list--item__details">
<h3>{item.name}</h3>
<p>{item.lastMessage}</p>
</div>
</div>
)
}
}
export default ListItem;
import React, { Component } from 'react';
import ViewWhatsapp from '../presentational/ViewWhatsapp';
import ViewChatHistory from './ViewChatHistory';
class View extends Component {
render(){
let visibility = this.props.visibility;
let view;
view = (visibility) ? <ViewChatHistory selectedContactChat={ this.props.selectedContact } /> : <ViewWhatsapp />
return(
<div className="view" style={{"display": "flex", "flexGrow": "1"}}>
{ view }
</div>
)
}
}
export default View;
import React, { Component } from 'react';
class ViewChatHistory extends Component{
render(){
console.log(this.props.selectedContactChat);
return(
<div className="view--chat" >
{
this.props.selectedContactChat.map( (contact) =>{
return (
<header key={contact.id} >
<div className="user-details">
<img src={contact.profilePhoto} style={{"width": "45px", "height": "40px", "borderRadius": "100%", "marginRight": "20px"}} alt={""}/>
<div className="user-details-name">
<h3>{contact.name}</h3>
</div>
</div>
<nav className="extra-icons" style={{"width": "120px", "display": "flex", "justifyContent" : "space-between", "marginTop" : "10px"}}>
<i className="material-icons"></i>
<i className="material-icons"></i>
<i className="material-icons"></i>
</nav>
</header>
)
})
}
</div>
)
}
}
export default ViewChatHistory;
Responsive design is not something you do "differently" in React. You've still got the same old HTML, CSS, JS running in the browser.
Read more about responsive design

Why won't my modal close when clicking the close button?

I've hit a wall and have no clue what to do. I'm simply trying to close my bootstrap modal but it just won't close. It opens fine but again it just won't close. I've tried so many ways to rectify this that there won't be enough space on this post to list all my attempts.
What am I doing wrong and how can I fix this?
Here's App.js:
import React, { Component } from 'react';
import Product from './Product';
import { ProductConsumer } from "../context";
import TitleBody from "./TitleBody";
import AboutButton from "./AboutButton";
import AboutButtonModal from "./AboutButtonModal";
export default class App extends Component {
constructor(props) {
console.log("Props - ", props);
super(props);
this.state = {
modalVisible: false
};
this.openModal = this.openModal.bind(this);
}
openModal() {
console.log("Open modal called ", this.state.modalVisible);
const modalVisible = !this.state.modalVisible;
this.setState({
modalVisible
}, console.log(this.state.modalVisible));
}
render() {
let styles = this.state.modalVisible
? { display: "block" }
: { display: "none" };
return (
<React.Fragment>
<div className="py-5">
<div className="container">
<TitleBody name="Welcome to" title="Cruskip"/>
<AboutButtonModal show={this.state.modalVisible} onClick={this.openModal} style={styles}/>
<AboutButton onClick={this.openModal}/>
</div>
</div>
</div>
</React.Fragment>
);
}
}
Here's AboutButtonModal.js:
import React from 'react';
import './AboutButtonModal.scss';
const Modal = ({ handleClose, show, children}, props) => {
const showHideClassname = show ? "modal display-block" : "modal display-none";
return(
<div className={showHideClassname} style={props.style}>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button
type="button"
onClick={props.onClick}
className="close"
>
×
</button>
<h4 className="modal-title">Modal Header</h4>
</div>
<div className="modal-body">
<p>Some text in the modal.</p>
</div>
<div className="modal-footer">
<button
onClick={props.onClick}
type="button"
className="btn btn-default"
>
Close
</button>
</div>
</div>
</div>
</div>
);
};
export default Modal;
Here's AboutButton.js:
import React from 'react';
import './AboutButton.scss';
const AboutButton = (props) => {
return(
<div className="row">
<button className="about-btn" type="button" onClick={props.onClick}>
About Us
</button>
</div>
);
};
export default AboutButton;
If you are using ({ handleClose, show, children }, props),It won't give you to access of props onClick function..
So to use props, just apply object destructing of props..Now,Your code will become like this...
const Modal = ({ handleClose, show, children,...props})

React Props Undefined

I am working on the React Recipe Box project from Free Code Camp. I have a parent component that displays recipe names, which it receives as props. The recipe name can be clicked to display a child component that then has the same props passed down to the child component to display information about the ingredients. My problem is, when I click the recipe name, the props in the parent component become undefined. Ive googled a bunch, but I cant figure out why this is happening. Has anyone run into this before?
import React, { Component } from 'react';
import ShowRecipe from './recipeDetail';
class RecipeDetail extends Component {
constructor(props){
super(props)
this.state = {
isHidden:true
}
}
render() {
return (
<div className="card">
<div className="card-header">
<h5>
<button
className="btn btn-link"
onClick={() => {
this.setState({isHidden: !this.state.isHidden})
}}
>
{this.props.recipe.recipeName}
</button>
</h5>
</div>
{ !this.state.isHidden &&
<ShowRecipe
ingredients={this.props.recipe.ingredientsList}
/>
}
</div>
);
}
}
export default RecipeDetail;
this is where the props for RecipeDetail are coming from:
import React from 'react';
import RecipeDetail from './recipeDetail';
import { Jumbotron, ListGroup } from 'react-bootstrap';
const RecipeBoxHolder = ({recipes}) =>{
const recipesItems = recipes.map((recipe) => {
console.log(recipes);
return(
<RecipeDetail
key={recipe.recipeName}
recipe={recipe}
/>
)
})
return(
<div>
<Jumbotron className="jtron">
<h5>Recipes</h5>
<ListGroup>
{recipesItems}
</ListGroup>
</Jumbotron>
</div>
)
}
export default RecipeBoxHolder;
TypeError: Cannot read property 'recipeName' of undefined
RecipeDetail.render
src/components/recipeDetail.js:22
19 | <button
20 | className="btn btn-link"
21 | onClick={() => {this.setState({isHidden:
!this.state.isHidden})}} >
> 22 | {this.props.recipe.recipeName}
23 | </button>
24 |
25 | </h5>
this comes from a different component where the user enters inputs and its passed to the main parent component for the app
let recipeObject={
recipeName: this.state.recipe,
ingredientsList: this.state.ingredients
};
component where user inputs data, takes data and passes it back up to main parent component
import React, {Component} from 'react';
import {ListGroupItem} from 'react-bootstrap';
class AddModal extends Component{
constructor(props){
super(props)
this.state={
recipe: '',
ingredients: ''
}
}
render(){
let recipeObject={
recipeName: this.state.recipe,
ingredientsList: this.state.ingredients
};
return(
<ListGroupItem>
<div className="card">
<div className="card-header">
<span>Add Recipe</span> <i className="fas fa-utensils"></i>
</div>
<div className="card-body">
<label>Recipe</label>
<input value={this.state.recipe} onChange={event =>
this.setState({recipe: event.target.value})} type="text"
className="form-control"/>
<label className="add-ingredients-label">Add Ingredients</label>
<textarea value={this.state.ingredients} onChange={event =>
this.setState({ingredients: event.target.value})}
className="form-control"></textarea>
</div>
<div className="card-footer">
<button className="close-button btn btn-outline-danger btn-
sm">
Close
<i className="fas fa-times"></i>
</button>
<button onClick={e =>{this.props.addRecipe(recipeObject)}}
className="btn btn-outline-success btn-sm">
Add Recipe
<i className="fas fa-plus"></i>
</button>
</div>
</div>
</ListGroupItem>
);
}
}
export default AddModal;
this is the main parent component:
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import RecipeBoxHolder from './components/recipeContainer';
import AddModal from './components/addRecipeModal';
import './style/index.css';
import {Button, Modal} from 'react-bootstrap';
class App extends Component{
constructor(props){
super(props);
this.state={
recipes:[],
showAddModal: false
}
}
render(){
const addRecipe = (recipeObject) =>{
this.setState(prevState => ({
recipes:[...prevState.recipes, recipeObject]}
))
}
return(
<div className="container">
<RecipeBoxHolder recipes={this.state.recipes} />
<Button
bsStyle="primary"
bsSize="large">
</Button>
<AddModal addRecipe={addRecipe} />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
#Esteban Trevino I put my findings into an answer because the comments become too long, however I do not have a solution as I could not reproduce your issue.
I copied your code into a create-react-app generated react scaffold, and it runs fine. In this gist you can see the file I made:
https://gist.github.com/femans/22324382a8e04390f6a0ece49b867708
I do want to point out that you should not use the recipeName as a key, because they are not unique by design. Better use the following construction:
const recipesItems = recipes.map((recipe, key) => {
return(
<RecipeDetail
key={key}
recipe={recipe}
...

React-Redux: Passing Event Handling inside map function

New to React/Redux, I am having hard time implementing on event handling.
I know that the 'this' reference key goes null when passed into the map (this.props.addRecipe.map of recipebox) function but I don't how to resolve it.
Essentially I would like to pass the onChange handler to ModalBox for each element in the array.
src/containers/recipebox
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ListGroup, ListGroupItem, Panel, Button, Modals } from 'react-bootstrap';
import MyModal from '../components/mymodal';
import { bindActionCreators } from 'redux';
import { deleteRecipe } from '../actions/index';
import shortid from 'shortid'
import ModalBox from '../containers/modalbox'
class RecipeBox extends Component {
constructor(props){
super(props);
this.renderRecipeList = this.renderRecipeList.bind(this)
this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
}
handleRecipeNameChange(event){
this.setState({recipeName: event.target.value})
}
handleUserIngredientsChange(event){
this.setState({userIngredients: event.target.value})
}
renderRecipeList(recipeItem, index){
const recipe = recipeItem.recipe;
const ingredients = recipeItem.ingredients;
const id = shortid.generate();
return(
<div key={id}>
<Panel bsStyle="primary" collapsible header={<h3>{recipe}</h3>}>
<ListGroup >
<ListGroupItem header="Ingredients"></ListGroupItem>
{ingredients.map(function(ingredient,index){
return <ListGroupItem key={index}>{ingredient}</ListGroupItem>;
})}
<ListGroupItem>
<Button
onClick={() => this.props.deleteRecipe(recipeItem)}
bsStyle="danger">Delete
</Button>
<ModalBox
modalTextTitle={'Edit Recipe'}
recipeName={recipe}
userIngredients={ingredients}
handleRecipeNameChange={this.handleRecipeNameChange}
handleUserIngredientsChange={this.handleUserIngredientsChange}
onClickSubmit={this.onClickSubmit}
/>
</ListGroupItem>
</ListGroup>
</Panel>
</div>
)
}
render(){
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(this.renderRecipeList)}
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
addRecipe : state.recipeState
};
}
function mapDispatchToProps(dispatch){
return bindActionCreators({deleteRecipe : deleteRecipe}, dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(RecipeBox);
src/containers/modalbox
import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
class ModalBox extends Component {
constructor(props){
super(props)
this.state = {
showModal: false
};
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal(){
this.setState({
showModal: !this.state.showModal
});
}
submitData(link){
link()
this.toggleModal()
}
render() {
return (
<div>
<Button
bsStyle="info"
onClick={this.toggleModal}
>
{this.props.modalTextTitle}
</Button>
<Modal show={this.state.showModal} onHide={this.toggleModal}>
<Modal.Header closeButton>
<Modal.Title>{this.props.modalTextTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<div className="form-group">
<label htmlFor="recipeName">Name of Recipe:</label>
<input
value={this.props.recipeName}
onChange= {this.props.handleRecipeNameChange}
type="text"
className="form-control"
id="recipeName" />
</div>
<div className="form-group">
<label htmlFor="userIngredients">Ingredients:</label>
<textarea
placeholder="you can seperate by comma"
value={this.props.userIngredients}
onChange={this.props.handleUserIngredientsChange}
type="text"
className="form-control"
id="userIngredients" />
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button
bsStyle="info"
onClick={ () => this.submitData(this.props.onClickSubmit) }>
{this.props.modalTextTitle}
</Button>
<Button
bsStyle="danger"
onClick= {this.toggleModal}
>Close</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
export default ModalBox
inside map function you need to change the this like below code,
render(){
const self = this;
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(self.renderRecipeList)}
</div>
</div>
)
}

Categories