Reactjs share link to state controlled page - javascript

I have a reactjs project that uses react route version 4 and react16.3 . I can navigate to page http://localhost:8000/#/my-list where it will take you to MyList Component , on my list component there is a link to view a single list which behaves like a SPA by changing the state as below .
import React,{Component} from 'react'
class MyList extends Component{
constructor(props){
super(props)
this.state={
canViewItem:false
}
this.viewItem=this.viewItem.bind(this)
}
viewItem(){
this.setState({canViewItem:true})
}
renderDisplay() {
const {canViewItem}=this.state
if(canViewOrder){
return <canViewItem cancel={this.cancel} item={item} />
}
else {
return this.renderMyList()
}
}
renderMyList(){
return(
<table>
<thead>
<tr>
<th>Iten Name</th>
<th>Quantity</th>
<th>More Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>Item 1</td>
<td>10</td>
<td>onClick={() => this.viewItem(item1Obj)}</td>
</tr>
<tr>
<td>Item 2</td>
<td>30</td>
<td>onClick={() => this.viewItem(item2Obj)}</td>
</tr>
</tbody>
</table>
}
render(){
return this.renderDisplay()
}
}
How do i share a link so as it takes me direct to an item page ?

Inside of componentWillMount() evaluate what is being passed in this.props.location.pathname. You should be able to grab the ID # from your URL and update your state.
I don't see how you are determining in your existing code which item they are viewing.
componentWillMount() {
let id = '';
console.log(this.props.location.pathname);
// write a JS function to parse the ID from the URL here and save to 'id'
// then if you have an ID, save whatever you need to state.
if(id !== '') {
this.setState({
canViewItem: true
});
}
}
As a side note, renderDisplay and renderMyList should be included in your constructor.

Related

Vue js send data from api to new page

I am new to Vue Js and I would like to know how I can send data between two components. I am building a vue app that gets a list of users from an api and displays them. I would like to know I can move data between two components so that I can view more details on a new page.
here is my html code to display the data in a table
<table class="table table-hover table-striped">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Occupation</th>
<th scope="col">Email</th>
<th scope="col">Bio</th>
<th scope="col">View</th>
<th scope="col">Edit</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" :key="user.id">
<th scope="row">{{ user.id }}</th>
<td>{{ user.name }}</td>
<td>{{ user.username}}</td>
<td>{{ user.email }}</td>
<td>{{ user.phonenumber}}</td>
<router-link to="/users" class="btn btn-primary">View</router-link>
</td>
<td>
<router-link #click="shareData" :key="user.id" to="/edit" class="btn btn-primary">Edit</router-link>
</td>
</tr>
</tbody>
</table>
this is my js code
<script>
import axios from "axios";
import moment from "moment";
export default {
name: 'Home',
created() {
this.getUsers();
},
data() {
return {
users: [],
};
},
methods: {
getUsers() {
axios
.get("https://607e868602a23c0017e8b79e.mockapi.io/api/v1/users")
.then((response) => {
console.log(response.data);
this.users = response.data;
})
.catch((error) => {
console.log(error);
});
},
format_date(value) {
if (value) {
return moment(String(value)).format("DD-MM-YYYY");
}
},
shareData(){
this.$router.push({name:"Users", params:{data:this.users}})
},
editData(){
}
},
};
where do how I move the data to the view and edit routes/components
You can use vue-router's dynamic route matching for this kind of problem. You can simply refactor your /user endpoint to /user/:id and in the component you are calling when landing on /user, you can simply make your api call and fill in the details. You need to update your first router link to have some id in the form of: /user/123 and in the component, you can get that id by calling this.$route.params.id.
Depending on the complexity of your Application, you may use VUEX to store all your Application's state, or if you have a small application and do want to spend time learning VUEX, you may simply use props. With props you can pass objects ( data ) to your components or even routes.
If you want to pass data from one sibling component to another sibling component ( components having same parent) then you can use Event Bus.
Here's an article which I used to learn Event Bus Event Bus Article
If you want to pass data from Parent component to child Component , you can simply use a props.
If you want to get data anywhere in your code , then use Vuex.
Vuex sure is very handy. Happy learning.

Error: Image is not display in CactusList Page

I am currently developing a ecommerce project using Laravel and react.js. I want to show the available cactus list in my admin panel. So, I created the table and add data to the table using laravel and react.js. The image is automatically saved to "cactus_Type" folder in the project folder. I want to show all the available cactus types that I have added to Database. So, I have created a table to show the available cactus. Only ID, Name is display on the table, the image is not display.
CactusController I use:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Cactus;
class CactusController extends Controller
{
//
function addCactus(Request $req)
{
$cactus=new Cactus;
$cactus->name=$req->input('name');
$cactus->file_path=$req->file('file')->store('cactus_Type');
$cactus->save();
return $cactus;
}
function Cactuslist()
{
return Cactus :: all();
}
function Cactusdelete($id)
{
$result= Cactus ::where('id',$id)->delete();
if($result)
{
return["result"=>"Cactus has been deleted"];
}
else
{
return["result"=>"Operation Failed"];
}
return $result;
}
}
Migration Cacti Table
public function up()
{
Schema::create('cacti', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('file_path');
$table->timestamps();
});
}
CactusList.js in react.js
import Cactus from './Cactus';
import React ,{useState,useEffect} from 'react';
import {Table} from 'react-bootstrap'
import {Link} from 'react-router-dom'
function CactusList()
{
//Define state
const [data,setData]=useState([]);
useEffect(()=>{
getData();
},[])
async function deleteOperation(id)
{
let result= await fetch("http://localhost:8000/api/Cactusdelete/"+id, {
method:'DELETE'
});
result=await result.json();
console.warn(result)
getData();
}
async function getData()
{
let result= await fetch("http://localhost:8000/api/Cactuslist");
result= await result.json();
setData(result)
}
return(
<div>
<Cactus/>
<div className="col-sm-8 offset-sm-2">
<h1>Available Cactus List</h1>
<Table>
<tr>
<td>Id</td>
<td>Name</td>
<td>Image</td>
<td>Operations</td>
</tr>
{
data.map((item)=>
<tr>
<td>{item.id}</td>
<td>{item.name}</td>
<td><img style={{width:100}} src ={"http://localhost:8000/"+item.file_path}/></td>
<td><span onClick={()=>deleteOperation(item.id)} className="delete">Delete</span></td>
<td>
<Link to={"updateCactus/"+item.id}>
<span className="update">Update</span>
</Link>
</td>
</tr>
)
}
</Table>
</div>
</div>
)
}
export default CactusList
I am getting this error in console
GET http://localhost:8000/cactus_Type/BEOPiwLF3EU9k2ggn8abKxAXgDVDpS38Up7UZ2OZ.jpg 404 (Not Found)
This is how the outcome show,
Available Cactus List Page
Thank you in advance for your help!

Sorting a table in React error

I have an application that loads up sizes and stock quantities for particular items, based on user input. Right now, I have two tables loading for each product, one for out of stock items and their sizes and one for in stock items and their sizes. I would like to be able to sort the In Stock table ascending/descending based on the quantity each size has.
So this picture below kinda shows the output as I have it right now. Two tables, one of them should have sorting capabilities.
My approach to this was to create an InStockTable component, where the sorting logic occurs. I'm using this codepen for reference. The difference between that one and mine is that I'm passing the table data as props to the component, rather than having it hardcoded in the component state.
This is the code for the component that handles each product:
class Product extends React.Component {
constructor(props) {
super(props);
}
renderRow(row) { // this function is for the rows of the out of stock table. These need not to be sorted.
return (
<tr key="row.size_id">
<td>{row.quantity}</td>
<td>{row.size_text}</td>
</tr>
);
}
renderSortableRow(row) { // this is for the rows that need to be sorted
var row = {
"quantity": row.quantity,
"size": row.size_text
}
return row;
}
renderProductDetails(product) {
const inStockProdStr = [];
const outStockProdStr = [];
if (product.length) { // product is an array
product.forEach(p => {
if (p.quantity == 0) {
outStockProdStr.push(this.renderRow(p))
}
else {
inStockProdStr.push(this.renderSortableRow(p))
}
});
}
else { // product is an object
if (typeof product == 'object') {
Object.keys(product).forEach(id => {
if (product[id].quantity == '0') {
outStockProdStr.push(this.renderRow(product[id]))
}
else {
inStockProdStr.push(this.renderSortableRow(product[id]))
}
}
);
}
}
return (
<div className={'product-tables'}>
<InStockTable stockArr={inStockProdStr} />
<div className={'out-stock'}>
<h5>Out Of stock</h5>
<table className={'table'}>
<thead className="thead-dark">
<tr>
<th scope="col">Qty</th>
<th scope="col">Size</th>
</tr>
</thead>
<tbody>
{outStockProdStr.map(p => p)}
</tbody>
</table>
</div>
</div >
);
}
render() {
return (
<div id="product-container">
<div id="product-info">
<h2>{this.props.productId}</h2>
<div id="product-line-detail">
{
this.renderProductDetails(this.props.prodStock)
}
</div>
</div>
</div>
);
}
}
This is the code for the In Stock table component:
class InStockTable extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className={'in-stock'}>
<h5>In stock</h5>
<table className={'table'}>
<thead className="thead-dark">
<tr>
<th scope="col">Qty</th>
<th scope="col">Size</th>
</tr>
</thead>
<tbody>
{
this.props.stockArr.map((s) => (
<tr key={s.simple_id}>
<td>{s.quantity}</td>
<td>{s.size_text}</td>
</tr>
))
}
</tbody>
</table>
</div>
);
}
}
If all this worked, I should be able to create a sorting function inside the inStock table component. However, I'm getting the following error:
Error: Objects are not valid as a React child (found: object with keys {quantity, size}). If you meant to render a collection of children, use an array instead.
in tbody (created by Product)
in table (created by Product)
in div (created by Product)
in div (created by Product)
in div (created by Product)
in div (created by Product)
in div (created by Product)
in Product (created by ProductList)
in ProductList (created by RequestForm)
in div (created by RequestForm)
in div (created by RequestForm)
in RequestForm
react-dom.development.js:59:15
The above error occurred in the <tbody> component:
in tbody (created by Product)
in table (created by Product)
in div (created by Product)
in div (created by Product)
in div (created by Product)
in div (created by Product)
in div (created by Product)
in Product (created by ProductList)
in ProductList (created by RequestForm)
in div (created by RequestForm)
in div (created by RequestForm)
in RequestForm
Any ideas? Is this the right way to sort?
The error just means that you are trying to render an object, as the p in {inStockProdStr.map(p => p)} is
{
"quantity": row.quantity,
"size": row.size_text
}
Change it to similar to what you did below (change { to ( so that the map function is actually returning the element):
{inStockProdStr.map((p) => (
<tr>
<td>{p.quantity}</td>
<td>{p.size}</td>
</tr>
))}
Silly mistake here. I was trying to display my InStockArr object in the OutStockArray area. The code now acts as expected and I've fixed the top to reflect.

ReactJs - Pass Parameters to Event handler [duplicate]

This question already has answers here:
React 'cannot read property of undefined' when using map
(4 answers)
Closed 5 years ago.
I've just started looking basics of ReactJs. Following is my component to show list of buses. What I want exactly is I want to perform edit/delete operations over buses. But not able to pass busId of corresponding bus to my edit/delete methods.
Following is component code
import React, {Component} from "react";
import { withRouter } from 'react-router-dom'
import {Table,Badge, Label,FormGroup,Container, Row, Col, CardGroup, Card, CardBlock,CardHeader, Button, Input, InputGroup, InputGroupAddon} from "reactstrap";
import {appSettings} from '../../../../Utils/Util.js';
import Pagination from "react-js-pagination";
var axios = require('axios');
class BusList extends React.Component {
constructor(props) {
super(props);
this.state = {
busList:[]
};
this.loadBuses = this.loadBuses.bind(this);
}
componentWillMount() {
this.loadBuses();
}
loadBuses() {
var url = ‘my-api-complete-url-here’;
axios.get(url)
.then((result) => {
var key = 0;
var buses = result.data.map(function(bus,i){
return <tr key={key++}>
<td key={key++}>{bus.id}</td>
<td key={(key++)}>{bus.number}</td>
<td key={(key++)}>
<Button onClick={(e)=>this.editBus(e, bus.id)}>Edit</Button>
<Button onClick={(e)=>this.deleteBus(e, bus.id)}>Delete</Button>
</td>
</tr>
});
this.setState({busList: buses});
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div className="animated fadeIn">
<Table hover responsive striped>
<thead>
<tr>
<th>Sr #</th>
<th>Bus Number</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{this.state.busList}
</tbody>
</Table>
</div>
);
}
editBus(id, e) {
console.log(‘Edit - Bus Id = ' +id);
}
deleteBus(id, e) {
console.log('Delete - Bus Id = ' +id);
}
}
export default BusList;
But when tapped on edit button, I receive this error(
Screenshot)
you're accessing it in wrong order, you're passing (e)=>this.editBus(e, bus.id) and in function you've defined editBus(id, e)
moreover you need to bind(this) at the end of map function
var buses = result.data.map(function(bus,i){
return <tr key={key++}>
<td key={key++}>{bus.id}</td>
<td key={(key++)}>{bus.number}</td>
<td key={(key++)}>
<Button onClick={(e)=>this.editBus(e, bus.id)}>Edit</Button>
<Button onClick={(e)=>this.deleteBus(e, bus.id)}>Delete</Button>
</td>
</tr>
});
Also, you don't need to define key variable. Instead, use second argument i of map function as it is the index of array element.
updated
you need to change your map code with
var buses = result.data.map(function(bus,i){
return <tr key={key++}>
<td key={key++}>{bus.id}</td>
<td key={(key++)}>{bus.number}</td>
<td key={(key++)}>
<Button onClick={(e)=>this.editBus(e, bus.id)}>Edit</Button>
<Button onClick={(e)=>this.deleteBus(e, bus.id)}>Delete</Button>
</td>
</tr>
}.bind(this));
The .bind(this) in the last line does the trick.

Why do enzyme not find 'tr' in a table?

I'm writting some test using enzyme but I have some weird behavior. Here is my test :
import React from 'react'
import { TypeTable } from 'routes/Type/components/TypeTable'
import { shallow } from 'enzyme'
import { Table } from 'react-toolbox'
// ...
let _props, _wrapper
beforeEach(() => {
_props = {
getTypes: sinon.spy(),
types: [
{ name: 'type 1'},
{ name: 'type 2'}
]
}
_wrapper = shallow(<TypeTable {..._props} />)
})
it('Should render a <Table>', () => {
expect(_wrapper.is(Table)).to.be.true
})
it('should render 2 rows', () => {
expect(_wrapper.find('tbody').find('tr')).to.have.length(2)
})
The first test is working. The second one is not working (the assertion is failing : expected { Object (root, unrendered, ...) } to have a length of 2 but got 0)
But in my second test, if I print the content of my _wrapper using console.log(_wrapper.html()) I get
'<table data-react-toolbox="table">
<thead>
<tr>
<th>name</th>
</tr>
</thead>
<tbody>
<tr data-react-toolbox-table="row">
<td>type 1</td>
</tr>
<tr data-react-toolbox-table="row">
<td>type 2</td>
</tr>
</tbody>
</table>'
Which seems to be ok and which contains several tr.
Did I missed something ?
shallow will not "render" subcomponents. It is used to test a single component and not its children. I think that using mount instead of shallow will let you test what you want.
Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren't indirectly asserting on behavior of child components.

Categories