React component in component - reactjs

I'm trying to do a <DropdownLink /> inside a <BootstrapDropdown /> in my code, but I dunno how to.
I've tried to solve the problem with React documentation, but I didn't find anything.
App.js
import React from 'react';
import '../scss/app.scss';
import BootstrapDropdown from './helpers/bootstrapDropdown';
import DropdownLink from './helpers/dropdownLink';
function App() {
return (
<div className="App">
<BootstrapDropdown name={"Dropdown"}>
<DropdownLink name={"Strona główna"} href={"/"} />
</BootstrapDropdown>
</div>
);
}
export default App;
dropdownLink.js
import React from 'react';
class DropdownLink extends React.Component {
render() {
return <a className="dropdown-item" href={this.props.href}>{this.props.name}</a>
}
}
export default DropdownLink;
bootstrapDropdown.js
import React from 'react';
class BootstrapDropdown extends React.Component {
render() {
return <div className="dropdown">
<button className="btn btn-secondary dropdown-toggle" type="button" id="dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{this.props.name}
</button>
<div className="dropdown-menu" aria-labelledby="dropdownMenuButton">
</div>
</div>
}
}
export default BootstrapDropdown;
I want to show a <DropdownLink /> inside a <div className="dropdown-menu"></div> in <BootstrapDropdown />.

You need to explicitly tell where to render the children:
import React from 'react';
class BootstrapDropdown extends React.Component {
render() {
return <div className="dropdown">
<button className="btn btn-secondary dropdown-toggle" type="button" id="dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{this.props.name}
</button>
<div className="dropdown-menu" aria-labelledby="dropdownMenuButton">
{this.props.children}
</div>
</div>
}
}
export default BootstrapDropdown;

Related

Hello i want to move an item from Todo list to done list in react js here is my code

Hello i want to move an item from todo list to delete list in ReactJS and i want to delete it from todo list when i move it to done list i did everything i can delete the selected item or all items but i cant add it to done list when i move it
import React from 'react';
import './App.css';
import Todoinput from './Components/Todoinput'
import Todolist from './Components/Todolist'
import Tododone from './Tododone'
import { render } from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import uuid from 'uuid';
class App extends React.Component {
state= {
items:[],
id:uuid(),
item:'',
editItem:false
}
handleChange = (e) => {
this.setState ({
item:e.target.value
})
}
handleSubmit = (e) => {
e.preventDefault ();
const newItem = {
id:this.state.id,
title:this.state.item,
};
const updatedItems = [...this.state.items,newItem]
this.setState ({
items:updatedItems,
item:'',
id:uuid(),
editItem:false
})
}
clearList = (e) => {
this.setState ({
items:[]
})
}
doneItem = (id) => {
const doneItems = this.state.items.filter (item => item.id !== id)
this.setState ({
items:doneItems
})
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-10 mx-auto col-md-8 mt-4">
<h3 className="text-capitalize text-center">Todo Inputs</h3>
<Todoinput item={this.state.item} handleChange={this.handleChange}
handleSubmit={this.handleSubmit}
/>
<Todolist items={this.state.items} clearList={this.clearList} doneItem={this.doneItem}/>
<Tododone doneItem={this.doneItem}/>
</div>
</div>
</div>
);
}
}
export default App;
/**/
import React from 'react'
import Todoitem from './Todoitem'
class Todolist extends React.Component {
render() {
const {items,clearList,doneItem}=this.props
return (
<ul className="list-group my-5">
<h3 className="text-capitalize text-center">todo list</h3>
{
items.map(item => {
return (
<Todoitem
key={item}
title={item.title}
doneItem={()=> doneItem(item.id)}
/>
)
})
}
<button type="button" className="btn btn-danger btn-block text-capitalize mt-5"
onClick={clearList}
>clear list</button>
</ul>
)
}
}
export default Todolist
/**/
import React from 'react'
class Todoinput extends React.Component {
render() {
const {item,handleChange,handleSubmit} = this.props
return (
<div className="card card-body my-3">
<form onSubmit={handleSubmit}>
<div className="input-group">
<div className="input-group-prepend">
<div className="input-group-text bg-primary text-white">
<i className="fa fa-book" ></i>
</div>
</div>
<input type="text" className="form-control text-capitalize" placeholder="Add A To Do Item"
value={item}
onChange={handleChange}
/>
</div>
<button type="submit" className="btn btn-block btn-primary mt-3">Add Item</button>
</form>
</div>
)
}
}
export default Todoinput
/**/
import React from 'react'
class Todoitem extends React.Component {
render() {
const {title,doneItem} = this.props
return (
<li className="list-group-item text-capitalize d-flex justify-content-between my-2">
<h6>{title}</h6>
<div className="todo-icon">
<span className="mx-2 text-sucess"onClick={doneItem}>
<i className="fa fa-window-close"></i>
</span>
</div>
</li>
)
}
}
export default Todoitem
/**/
import React from 'react'
class Tododone extends React.Component {
render() {
const {items,clearList,doneItem,title}=this.props
return (
<div>
<h2 className="text-capitalize text-center">Done Items</h2>
<li className="list-group-item text-capitalize d-flex justify-content-between my-2">
<h6>{doneItem}</h6>
<div className="todo-icon">
<span className="mx-2 text-danger" onClick={doneItem}>
<i className="fa fa-trash"></i>
</span>
</div>
</li>
<button type="button" className="btn btn-danger btn-block text-capitalize mt-5"
onClick={clearList}>clear list</button>
</div>
)
}
}
export default Tododone
so if anyone can help Please i post all the code above if anyone can help me please <3
I've played around a bit with your code in here Sandbox
Essentially what I've done is move your state into hooks, and given each item an isComplete property, so you can have 2 lists, 1 complete and 1 incomplete.
It's not a full solution, but should give you a basic idea of how to manage your lists.
These are the 2 lines that give you your complete and incomplete items
const incompleteItems = items.filter(x => !x.isComplete);
const completeItems = items.filter(x => x.isComplete);

React js communication between parent and child component using props send data from shop to prod details component

This is a shop Component which is the parent component in which I have an image on click handler in which I need to send data to a child component called Prod Details.
And the click event is detailMovie so need to pass it to child using props
The child component should should display the selected data from the function
import React from "react";
import { Link, browserHistory } from "react-router";
import { ProdDetails } from "./ProductDetails";
// import ProductsJSON from "../data/products.json";
export class Shop extends React.Component {
// to route to details page from list
onNavigateProdDetails() {
browserHistory.push("/proddetails");
}
constructor(props) {
super(props);
this.state = {
data: [],
selectedData: {}
};
}
//API Call to fetch data
componentDidMount() {
fetch("https://facebook.github.io/react-native/movies.json")
.then(Response => Response.json())
.then(findresponse => {
console.log(findresponse.movies);
this.setState({
data: findresponse.movies
});
});
}
detailMovie(moviedata) {
//this.props.clickedItem = moviedata;
this.selectedMovieList = moviedata;
};
render() {
// find the clicked item and local storage
let selectedMovie;
return (
<div className="shop pad-30">
<h1>Latest Arrivals</h1>
<div className="shop-inner">
<div className="prods-wrap">
{this.state.data.map((moviedata, i) => {
return (
<div
key={moviedata.id}
onClick={() => this.detailMovie(moviedata)}
data-key={moviedata.id}
className="shop-inner-each"
>
<Link to="/proddetails">
<div className="shop-inner-each-img">
<img src={moviedata.image} className="img-fluid" />
</div>
</Link>
<div className="shop-inner-each-details">
<div className="shop-inner-each-details-left">
<Link to="/proddetails">
<h3>{moviedata.title}</h3>
</Link>
<p>$ {moviedata.releaseYear}</p>
</div>
<div className="shop-inner-each-details-right">
<button type="button" className="fi flaticon-like" />
<button
type="button"
className="fi flaticon-shopping-cart"
/>
</div>
</div>
</div>
);
})}
</div>
</div>
</div>
);
}
}
import React from "react";
import { browserHistory, Link } from "react-router";
export class ProdDetails extends React.Component {
onNavigateShop() {
browserHistory.push("/shop");
}
constructor(props) {
super(props);
// copy current list of items
}
render() {
return (
<div className="proddetails">
<div className="proddetails-left">
<img src="" />
</div>
<div className="proddetails-right">
<div className="proddetails-right-inner">
<Link to="/shop" className="btn btn-pagination">
<i className="fi flaticon-left-arrow" /> Back
</Link>
{/* <h2>{this.props.movieData.title}</h2>
<h3>$ {this.props.movieData.releaseYear}</h3> */}
{/* <p>{this.updatedItem.description}</p> */}
<div className="actions">
<button type="button" className="btn btn-prime">
<i className="fi flaticon-like" /> Add to Wishlist
</button>
<button type="button" className="btn btn-prime">
<i className="fi flaticon-shopping-cart" /> Add to Cart
</button>
</div>
</div>
</div>
</div>
);
}
}

Understanding React browser history

I am building a web app using react 16 and react-router v4. My app has index.js like this -
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import Bootstrap from "bootstrap/dist/css/bootstrap.css";
import 'font-awesome/css/font-awesome.min.css';
import "../assets/css/clean-blog.css";
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter> ,
document.getElementById('app')
);
My App.js looks like this -
"use strict";
import React from "react";
import Header from "./layout/header";
import Body from "./layout/body";
import Footer from "./layout/footer";
class App extends React.Component {
render() {
return (
<div>
<Header />
<Body />
<Footer />
</div>
);
}
};
export default App;
In my Header component, I have a search box and I want that when user clicks on seacrh submit button, then they should be redirected to /seacrh url. I managed to get that. Please look at handleSubmit function
"use strict";
import React from "react";
import { Link } from 'react-router-dom';
import Notifications, {notify} from 'react-notify-toast';
import { withRouter } from 'react-router-dom';
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
searchTerm:''
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({searchTerm: event.target.value});
}
handleSubmit(event) {
event.preventDefault();
//console.log(this.props);
//console.log(this.state.searchTerm);
this.props.history.replace({
pathname:'/search',
searchTerm:this.state.searchTerm
});
}
render() {
return (
<nav className="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div className="container">
<Link to='/'>My Library</Link>
<button className="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
Menu
<i className="fa fa-bars"></i>
</button>
<div className="collapse navbar-collapse" id="navbarResponsive">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link to='/'>Home</Link>
</li>
<li className="nav-item">
<Link to='/authors'>Authors</Link>
</li>
<li className="nav-item">
<Link to='/books'>Books</Link>
</li>
</ul>
<form className="form-inline my-2 my-lg-0" onSubmit={this.handleSubmit} type="post">
<input className="form-control mr-sm-2" type="text" placeholder="Search" onChange={this.handleChange} name="searchTerm"/>
<button className="btn btn-outline-secondary btn-md " type="submit">Search</button>
</form>
</div>
</div>
</nav>
);
}
};
export default withRouter(Header);
This works fine when for all urls except when I try to submit from /search url then nothing happens. What I mean is that handleSubmit function gets called but then it does not fire the redirect call.
I am very new to react and would like to have some insight on how best should I handle this.

Pass map's argument to function in ReactJS

I am trying to make a todoList by ReactJS. I want to delete an item by its id, but when I console.log(id), it returns undefined. Here is my code
App.js:
import React, { Component } from 'react';
import './App.css';
import Header from './Components/header';
import InputTodo from './Components/todoInput';
class App extends Component {
constructor(props){
super(props);
this.state={
todos:[
{id:0,text:'Make dinner'},
{id:1,text:'Fold the laundary'},
{id:2,text:'Do homework'}
]
}
}
addHere=(text)=>{
this.setState({
todos:this.state.todos.concat([text])
})
}
removeHere=(id)=>{
console.log(id);
// let arr=this.state.todos;
// let index=arr.findIndex((x)=>x.id===id);
// console.log(index);
}
render() {
return (
<div className='todo-wrapper'>
<Header/>
<InputTodo todoText='Type Here...' addTodo={this.addHere}/>
<div>
{this.state.todos.map((value,key)=>{
return (
<div className='row myList' key={key}>
<p className='col-xs-10'> {value.text}-{value.id} </p>
<button className='btn btn-danger pull-right col-xs-2' onClick={this.removeHere(value.id)}>Delete</button>
</div>
)})}
</div>
</div>
);
}
}
export default App;
The following is InputTodo.js:
import React, {Component} from 'react';
import '../App.css';
export default class InputTodo extends Component{
constructor(props){
super(props);
this.state={
todoInput:{
id:2,
text:''
}
}
}
handleSubmit=(e)=>{
if(this.refs.title.value===''){
alert('You must input something');
}
else{
this.state.todoInput={
id:this.state.todoInput.id+1,
text:this.refs.title.value
};
this.setState(this.state);
this.props.addTodo(this.state.todoInput);
this.refs.title.value='';
}
e.preventDefault();
}
render(){
return(
<form className='input-group' onSubmit={this.handleSubmit}>
<input type='text' ref="title" className='form-control'placeholder={this.props.todoText}/>
<span className='input-group-btn'>
<input type='submit' value='Submit' className='btn btn-primary' />
</span>
</form>
);
}
}
While FuzzyTree's answer will work, a cleaner approach would be extracting the todo item's JSX into its own component. This would have the added benefit of not creating a new function for the button's onClick prop every time App's render function gets called.
The component might look like this:
// TodoItem
class TodoItem extends Component {
handleRemove = () => this.props.onRemove(this.props.id)
render() {
return (
<div className='row myList'>
<p className='col-xs-10'> {this.props.text}-{this.props.id} </p>
<button className='btn btn-danger pull-right col-xs-2' onClick={this.handleRemove}> Delete </button>
</div>
)
}
}
// App render
render() {
return (
<div className='todo-wrapper'>
<Header/>
<InputTodo todoText='Type Here...' addTodo={this.addHere}/>
<div>
{this.state.todos.map(({ id, text }, key) =>
<TodoItem key={key} id={id} text={text} onRemove={this.removeHere} />
)}
</div>
</div>
);
}

Get value of input and give to parent in React

I have the following two components App and it's child Toolbar.
Toolbar contains a form and and input, and I would like to pass the value from the input up to the App component's state -- but only when the use has confirmed it (on submit or enter etc).
My current attempt is not working as I only get a proxy and an event object back (which does makes sense). How would I do this?
I am not using Redux or anything like it.
App.js
import React, {Component} from 'react'
import {render} from 'react-dom'
import {} from './styles/base.scss'
import ImageContainer from './components/Images'
import Toolbar from './components/Toolbar'
export default class App extends Component {
constructor(props) {
super(props);
// http://www.cloudypoint.com/Tutorials/discussion/javascript-how-to-update-parents-state-in-react/
this.setFolderPathHandler = this.setFolderPathHandler.bind(this);
}
setFolderPathHandler(e) {
e.preventDefault();
console.log(arguments);
// this.setState({
// xyz: input
// });
}
render() {
return (
<div>
<Toolbar setFolderPathHandler={this.setFolderPathHandler} />
<ImageContainer />
</div>
)
}
}
Toolbar/index.js
import React, { Component } from 'react';
import path from 'path';
class Toolbar extends Component {
render() {
return (
<nav className="toolbar">
<div className="column">
{/* START used to be it's own component */}
<form onSubmit={this.props.setFolderPathHandler}>
<div className="form-field">
<input type="text" className="folder-path" ref={(input) => this.input = input} />
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
{/* END used to be it's own component */}
</div>
<div className="column">
<button><i className="fa fa-fw fa-2x fa-chevron-left" aria-hidden="true"></i></button>
<button><i className="fa fa-fw fa-2x fa-chevron-right" aria-hidden="true"></i></button>
</div>
</nav>
);
}
}
export default Toolbar;
I did have the input as a separate component but it was too confusing to me (I am new to React).
App.js
import React, {Component} from 'react'
import {render} from 'react-dom'
import {} from './styles/base.scss'
import ImageContainer from './components/Images'
import Toolbar from './components/Toolbar'
export default class App extends Component {
constructor(props) {
super(props);
// http://www.cloudypoint.com/Tutorials/discussion/javascript-how-to-update-parents-state-in-react/
this.setFolderPathHandler = this.setFolderPathHandler.bind(this);
}
setFolderPathHandler(inputValue) {
// this.setState({
// xyz: inputValue
// });
}
render() {
return (
<div>
<Toolbar setFolderPathHandler={this.setFolderPathHandler} />
<ImageContainer />
</div>
)
}
}
Toolbar/index.js
import React, { Component } from 'react';
import path from 'path';
class Toolbar extends Component {
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
}
submit(event) {
event.preventDefault();
this.props.setFolderPathHandler(this.input.value);
}
render() {
return (
<nav className="toolbar">
<div className="column">
{/* START used to be it's own component */}
<form onSubmit={this.submit.bind(this)}>
<div className="form-field">
<input type="text" className="folder-path" ref={(input) => this.input = input} />
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
{/* END used to be it's own component */}
</div>
<div className="column">
<button><i className="fa fa-fw fa-2x fa-chevron-left" aria-hidden="true"></i></button>
<button><i className="fa fa-fw fa-2x fa-chevron-right" aria-hidden="true"></i></button>
</div>
</nav>
);
}
}
export default Toolbar;
First, if you want to track input value in toolbar, you should save it into state:
class Toolbar extends Component {
constructor(...args) {
super(...args)
this.state = {text: ''};
}
onTextChange(event) {
const text = event.target.value;
this.setState({text});
}
onSubmit(event) {
event.preventDefault();
this.props.setFolderPathHandler(this.state.text);
}
render() {
return (
<nav className="toolbar">
<div className="column">
<form onSubmit={this.onSubmit.bind(this)}>
<div className="form-field">
<input type="text" className="folder-path" value={this.state.text} onChange={this.onTextChange.bind(this)} />
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
</div>
...
</nav>
);
}
}
export default Toolbar;
Note that we are keeping internally the value of the input and we are not passing the native events up to the parent controller.
Then in the parent controller:
setFolderPathHandler(input) {
// do something with the input
}
This solution has the problem that you cannot reset the input value from the parent component unless the component is removed from DOM and added again.
This is usually solved by putting the state to the parent component. The parent can then pass text and onChange handlers to the child that contains the <input> or, the parent can create the <input> and pass it to the child component as a property. Consider:
class Toolbar extends Component {
render() {
return (
<nav className="toolbar">
<div className="column">
<form onSubmit={this.props.onSubmit}>
<div className="form-field">
{this.props.textInput}
<button><i className="fa fa-fw fa-2x fa-folder-open" aria-hidden="true"></i></button>
</div>
</form>
</div>
...
</nav>
);
}
}
and App:
export default class App extends Component {
...
render() {
const textInput = (
<input ... value={this.state.text} onChange={this.onTextChange} />
);
return (
<div>
<Toolbar onSubmit={this.onSubmit} textInput={textInput} />
<ImageContainer />
</div>
)
}
}
This allows to separate components that handle the business logic (have state, smart components) and the components that only present things (stateless, dumb components).

Resources