1

I'am newbie on ReactJs, I want when I select the product name the price will be displayed, after that I put the Quantity and the total column will be displayed the result of Quantity*Price. I try to display the price, but the problem the total column always displayed NaN. As you can see the code below :

class AjouterFacture extends Component {
  constructor(props) {
    super(props);
    this.state = {

      rowData: [],

      Produits: [],
      Quantite: "",
      Prix: [],

      id: 0
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleRowDelete = this.handleRowDelete.bind(this);
    this.handleRowAdd = this.handleRowAdd.bind(this);
    this.handleQuantiteChange = this.handleQuantiteChange.bind(this);
    this.handleselectprdtChange = this.handleselectprdtChange.bind(this);
    this.PrixDisplay = this.PrixDisplay.bind(this);
    this.TotalDisplay = this.TotalDisplay.bind(this);

  }
  componentWillReceiveProps(nextProps) {
    console.log("nextProps", nextProps);
  }
  componentDidMount() {
    axios({
      method: "get",
      url: "/app/getNomprod/",
      withCredentials: true,
    }).then(response => {
      if (response && response.data) {
        this.setState({
          Produits: response.data
        });
      }
    }).catch(error => console.log(error));

  }
  handleQuantiteChange(index, value) {
    const rowDataCopy = this.state.rowData.slice(0);
    rowDataCopy[index] = Object.assign({}, rowDataCopy[index], {
      Quantite: parseInt(value, 10)
    });
    this.setState({
      rowData: rowDataCopy
    });
  }
  handleselectprdtChange(index, value) {
    const rowDataCopy = this.state.rowData.slice(0);
    rowDataCopy[index] = Object.assign({}, rowDataCopy[index], {
      selectprdt: value
    });
    this.setState({
      rowData: rowDataCopy,
    });
  }

  render() {

    let {
      Clients
    } = this.state.Clients;
    var Cd = {
      pointerEvents: 'none'
    }
    let {
      Produits
    } = this.state;
    let {
      rowData
    } = this.state.rowData;
    let {
      Prix
    } = this.state.Prix;

    return (<div className="animated fadeIn">



 <h6>  <Label ><strong>Veuillez ajouter au moins un produit :  </strong></Label></h6>
        <Table responsive style={items} >
        <thead style={back}>
                  <tr>
                    <th>PRODUIT</th>
                    <th>QUANTITE</th>
                    <th>PRIX UNITAIRE</th>
                    <th>TOTAL</th>
                    <th></th>
                  </tr>
                  </thead>
                  <tbody>
                {this.state.rowData.map((data, index) => (
              <tr key={index} id={index}>
                <td>
                  {" "}  <Input type="select" name="selectedcl" id="selectcl"
                          placeholder="Veuillez sélectionner un produit"  value={data.selectprdt}
                    onChange={(e) => this.handleselectprdtChange(index, e.target.value)} >
           <option  key={-1} hidden>Choisisr un produit</option>


                     {  this.state.Produits.map((pdt, i) => 
                     <option key={i}>{pdt.Nomp}</option>
                     )} 

                      </Input>
                    </td>
                    <td><Input type="number" 
                          value={data.Quantite || 0} onChange={(e) => this.handleQuantiteChange(index, e.target.value)}/></td>
                    <td>
                     {  this.state.Prix.map((pr, k) => 
                     <p key={k} >{pr.PrixV} </p>
                     )} 

                        </td>
                <td  > 
                     <p key={index} className='pa2 mr2 f6'>{(data.Quantite || 0) * (parseInt(this.PrixDisplay(data.selectprdt)))}  </p>
                    </td>
                    <td>
                     <Button onClick={(e) => this.handleRowDelete(index)} active style={center}  size="sm" color="danger" className="btn-pill" aria-pressed="true">Effacer</Button>
      </td>{" "}
              </tr>
            ))}  
                  <tr>parseInt(
            <td/>
            <td/>
            <td/>
            <td/>
            <td><Button onClick={this.handleRowAdd} active style={center}  size="sm" color="info" className="btn-pill" aria-pressed="true">Ajouter une ligne</Button></td>
          </tr>
        </tbody>

        <tfoot>
          <tr>

            <th></th>

            <th></th>
          </tr>
</tfoot>
        </Table>

        </div>
);
  }
  PrixDisplay(selectprdt) {
    return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
     if (response && response.data) {
        this.setState({
          Prix: response.data
        });
      }
    }).catch(error => {
      console.error(error);

    });
  }
  TotalDisplay(){


   return   this.state.Prix.map(pr =>
      parseInt(pr.PrixV));



  }

  handleRowDelete(row) {
    const rowDataCopy = this.state.rowData.slice(0);
    rowDataCopy.splice(row, 1);
    this.setState({
      rowData: rowDataCopy
    });
  }
  handleRowAdd() {
    let id = this.state.id;
    id = id++;
    const rowDataCopy = this.state.rowData.slice(0);
    rowDataCopy.push({
      selectprdt: "",
      Quantite: 0,
      Prix: 0
    });
    this.setState({
      rowData: rowDataCopy,
      id: id
    });
  }
}
export default AjouterFacture;

How can I display it ?

Melissa
  • 135
  • 1
  • 8
  • what you see here if you do `console.log(rowTotals)` ? I think `(row.Quantite * row.PrixV)` evalutes to `NaN` for some entries. – Arup Rakshit Aug 18 '18 at 15:12
  • @ArupRakshit No, I edit the code, my issue is about this column : `

    {(data.Quantite || 0) * (parseInt(this.PrixDisplay(data.selectprdt)))}

    `
    – Melissa Aug 18 '18 at 15:35

2 Answers2

1

Bonjour Melissa !

I think you try to display a value with :

{(data.Quantite || 0) * (parseInt(this.PrixDisplay(data.selectprdt)))}

But I see PrixDisplay is a function that do not return integer or everything else than a Promise. So, in fact you seems to multiply data.Quantite with a parseInt of a NaN value try snippet below.

In your case I think you need to :

  1. Declare in your state displayedPrice : 0 (if Prix isn't the same thing)
  2. Use {(data.Quantite || 0) * (this.state.displayedPrice || 0)}
  3. Call your PrixDisplay(data.selectprdt) function who already set Prix in your state. When you need it.
  4. And voilà ! When axios get the response, the setState function will update Prix and displayedPrice and that will trigger a re-render of your component who display the good value.

Bien à toi.

console.log(2 * parseInt(Promise.resolve()))
S.C.
  • 39
  • 4
  • Thank you @S.C, you mean I edit this.setState to `this.setState({ Prix: response.data, displayedPrice : 0 });` and `(this.state.displayedPrice || 0)` ? – Melissa Aug 18 '18 at 16:42
  • Yep, Like that, you'll be able to trigger `this.PrixDisplay()` function whenever you want (on user action, product / quantity change etc...) – S.C. Aug 18 '18 at 17:10
  • when I edit my code as you post,The price column is not displayed and the column Total display to 0, but when I change that by `{(data.Quantite || 0) * (parseInt(this.PrixDisplay(data.selectprdt)))}` the price will be displayed and the column display to NaN and I need both of them will be displayed.. – Melissa Aug 18 '18 at 17:14
1

According to your DOM, it appears that you're expecting the function PrixDisplay to return a value.

<td > <p key={index} className='pa2 mr2 f6'>{(data.Quantite || 0) * (parseInt(this.PrixDisplay(data.selectprdt)))} </p> </td>

However your function only sets state i.e., it does not return anything. Additionally, you will need to set the right value in the price array with the new value like so:

PrixDisplay(index, selectprdt) {
 const priceArray = this.state.Prix;
 return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
  if (response && response.data) {
    priceArray[index] = response.data;
    this.setState({ //<---- You're doing just a setState and not returning anything.
      Prix: priceArray
    });
  }
 }).catch(error => {
  console.error(error);

 });
}

What you can do instead is

{(data.Quantite || 0) * (parseInt(this.state.Prix[index].PrixV || 0))}
dkulkarni
  • 2,780
  • 4
  • 27
  • 36
  • when I edit my code by `{(data.Quantite || 0) * (parseInt(this.state.Prix[index] || 0))}` The price column is not displayed and the column Total display to 0, but when I change that by `{(data.Quantite || 0) * (parseInt(this.PrixDisplay(data.selectprdt)))}` the price will be displayed and the column display to NaN and I need both of them will be displayed.. – Melissa Aug 18 '18 at 17:15
  • I have updated my answer. I believe you will need to do `parseInt(this.state.Prix[index].PrixV || 0))` – dkulkarni Aug 19 '18 at 04:20
  • It 's still the same issue @dkulkarni Can I share the git file ? – Melissa Aug 19 '18 at 09:46
  • Yup I can take a look – dkulkarni Aug 19 '18 at 09:48
  • https://gist.github.com/IchrakMansour/94e1672245be090a45555e4190cf5e8a I want when I select the product name its price will be displayed, my issue is the price is displayed the same for others row and the issue of total.This is : https://stackoverflow.com/questions/51912740/having-the-same-value-of-price-and-total-column-using-reactjs – Melissa Aug 19 '18 at 09:58
  • Okay so the problem is you're resetting `Prix` in your state. What you should be doing is updating only the specified index in the array. Sort of like how you've done in `handleQuantiteChange`. Pass an `index` as another parameter to something like `PrixDisplay(index, selectprdt)`. I have updated my answer too. – dkulkarni Aug 19 '18 at 11:45
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/178298/discussion-between-melissa-and-dkulkarni). – Melissa Aug 19 '18 at 11:59