Home > OS >  React JS - Pass props from a navlink to a component
React JS - Pass props from a navlink to a component

Time:11-01

I generate a link with a "navlink" in a component called "ProductCard" and I want to pass the props to a component called "Product"

ProductCard Component

import React, {Component} from "react";
import {NavLink} from "react-router-dom";

class ProductCard extends Component{

render() {

    return (
        <div className="col-xl-4 col-md-6 col-xs-12">
            Name : {this.props.product.name}<br/>
            Price : {this.props.product.price}<br/>

            <NavLink
                to={{
                    pathname:"/product/"    `${this.props.producto.id}`,
                    aboutProps:{
                        product_id: `${this.props.product.id}`,
                        product_name: `${this.props.product.name}`,
                        product_sku: `${this.props.product.sku}`,
                    }
                }}
                exact
            > Show product
            </NavLink>

        </div>
    );
}
}

export default ProductCard;

Product.js Component

import React, {Component} from "react";

class Product extends Component{

constructor(props) {
    super(props);
    console.log(props.location.aboutProps);
    this.state = {
        products: []
    }
}


render() {

    return (

            <div className="app container" style={{backgroundColor: "red", padding: "10px"}}>

                Product<br/>

            </div>

    );
}
}

export default Product;

As I say, the problem I have is being able to pass the properties of the parent ProductCard component to the Child Product component

CodePudding user response:

EDIT: change to using state instead

state: {
      product_id: this.props.product.id,
      product_name: this.props.product.name,
      product_sku: this.props.product.sku
}

Access the props like this: props.location.state.product_id

CodePudding user response:

TLDR: Change your approach. Example with pointers

Example here https://codesandbox.io/s/brave-visvesvaraya-81c0p?file=/src/App.js

In addition to @ilernet answer, I would like to give a few tips on your code:

With the solution above your links will end up like /products/1/test/1223345. This is not a good practice if you have lots of data

const linkData = await fetch(`/productdata`);
// linkData will equal array of 10 products
// { id: 1, sku: 1, name: "Product 1"}

linkData.forEach(data => {
 return (
     <NavLink
       to={{
        pathname:"/product/"    `${data.id}`,
        aboutProps:{
           product_id: `${data.id}`,
           product_name: `${data.name}`,
           product_sku: `${data.sku}`,
         }
       }}
       exact
     > 
      Show product
    </NavLink>
);
}

BUT

With React you should load as much data as needed by each component.

Recommendations

  1. Change your link approach
// This accepts anything like /product/123
<Route
   exact
   path="/product/:id"
   render={({ match }) => {
    // Render can be used to instead of state - to inject props directly into a component 
    return <ProductCard id={Number(match.params.id)} />;
   }}
 />
  1. Fetch your data inside the Product/ProductCard Component
import React, { Component } from "react";

class ProductCard extends Component {
  constructor(props) {
    super(props);

    // Replaces a fetch()/API request
    this.state = {
      products: [
        {
          id: 123,
          name: "Test",
          price: 1234
        }
      ]
    };
  }
  render() {
    const { name, price } = this.currentProduct;
    return (
      <div className="col-xl-4 col-md-6 col-xs-12">
        Name : {name}
        <br />
        Price : {price}
        <br />
      </div>
    );
  }

  get currentProduct() {
    const { id } = this.props;

    if (!id) {
      return {
        name: "No Item",
        price: 0
      };
    }

    const { products } = this.state;
    const currentProduct = products.find((product) => product.id === id);
    return {
      name: (currentProduct && currentProduct.name) || "No Item",
      price: (currentProduct && currentProduct.price) || 0
    };
  }
}

export default ProductCard;

  • Related