Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Killeon Patterson
Killeon Patterson
18,528 Points

Passing arrays from one component to another, using props.

import React, { Component } from 'react';
import StatLine from "./statLine.component";
import axios from 'axios';

  function Users(props) {
  return <tr>
      <td>{props.users.name}</td>
      <td>{props.users.kind}</td>
      <td>{props.users.email}</td>
      <td>
       <a href="#" onClick={() => { props.deleteMenu(props.users._id) }}>delete</a>
      </td>
    </tr>
  }


export default class MenuItems extends Component {
  constructor(props) {
    super(props);

    this.deleteMenu = this.deleteMenu.bind(this);
    this.emailList = this.emailList.bind(this);


    this.state = {
      users: []

    };
  }

   componentDidMount() {
      axios.get('http://localhost:5000/users/')
        .then(response => {
            this.setState({ users: response.data })
          })
          .catch((error) => {
            console.log(error);
          })
      }



  deleteMenu(id) {
    axios.delete('http://localhost:5000/users/'+id)
      .then(res => console.log(res.data));
    this.setState({
      users: this.state.users.filter(el => el._id !== id)
    })
  }


  emailList() {
     return this.state.users.map(userEmail => {
       console.log(userEmail.email);
//returning props array
//returning props array
//returning props array
//returning props array
       return <StatLine ema={userEmail.email}/>;
       })

  }

    usersList() {
      this.emailList();
      return this.state.users.map(currentusers => {
        return <Users users={currentusers} deleteMenu={this.deleteMenu} key={currentusers._id}/>;
      })
    }


  render() {
    return (



      <div>
        <h3 >Customers</h3>
        <table className="table">
          <thead className="thead-light">
            <tr>
              <th>name</th>
              <th>kind</th>
              <th>email</th>
              <th>Actions</th>
            </tr>
            </thead>
            <tbody>
              { this.usersList() }
            </tbody>
          </table>
        </div>
    )
  }
}
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function LilStat(props) {
let start = "none";



return (
  <div
  style={{border: "solid", borderWidth: "2px", borderColor: "#cce0ff", borderRadius: "10px"}}
  className="shadow-sm p-2 mb-3 bg-white   card">
  <div className="card-body">
    <h3 style={{color: "#303030", fontWeight: "bold", fontFamily: "Times Roman", letterSpacing: "1px"}}
    onClick={() => {props.displayOrder(props.status.ourId)}}>{props.status.ourId}</h3>
    <h2 style={{color: "#0047b3"}}>"{props.status.ready}"</h2>
    <p style={{fontSize: "2.2em"}} >{props.status.timeMan} min</p>

    <div>

    <button type="button" value="button"  className="btn btn-success btn-sm"
    className="btn btn-outline-success btn-sm"
    style={{ marginLeft: "2%", marginRight:"1%", fontWeight: "bold"}}
     onClick={() => {props.tisGift(props.status.ourId)}}> a gift</button>

     <button type="button" value="button" className="btn btn-danger btn-sm" style={{fontWeight: "bold",  color: "white", marginLeft: "6px"}}
     onClick={() => { props.deleteButton(props.status._id) }}> - </button>

     <div className={props.status.ourId}  style={{marginLeft: "1%", display: "none"}}>
<div style={{display: "inline-block"}}>
     <button type="button" value="button"  className="btn btn-warning btn-sm" style={{
      color: "white", fontWeight: "bold"}}
      onClick={() => { props.sendGift(props.gifted, props.status.ourId)}}> send gift</button>
  </div>
  <div style={{display: "inline-block", marginTop: "2%"}}>
   <input
   style={{fontWeight: "bold", color: "grey", marginLeft: "4%"}}
     className="gift"
     placeholder=" please type in a valid email"
     value={props.forGift}
       onChange={props.giftedName}
       type="text"
     />
     </div>

    </div>
    </div>

    </div>
  </div>

)}

function EditRun(props) {
return (

    <button type="button" style={{fontWeight: "bold"}} className="btn btn-outline-secondary"
    onClick={() => props.showDelete()}> Edit Account </button>


)}
function DeleteRun(props) {
return (
  <div>
  <button type="button" value="button" className="btn btn-outline-warning"  style={{fontWeight: "bold"}}
  onClick={() => { props.closeDelete()}}> Close Edit </button>
  <button type="button" value="button" className="btn btn-outline-danger" style={{fontWeight: "bold", marginLeft: ".3em"}}
   onClick={() => { props.accountDelete()}}> Delete Account </button>
  </div>


)}


  const StatLine = props => {

 const [showDelete, setShowDelete] = useState(false);
 const [giftedAction, setGifted] = useState("");
 const [showGiftAction, setShowGift] = useState('');
 const [statusCon, setStatusCon] = useState([]);



   useEffect(
     () => {
      axios.get('http://localhost:5000/users/status', { headers:
        {
        "this-token": localStorage.getItem("this-token")
      }
      })
      .then(response => {
            setStatusCon(response.data);
          //console.log props from the MenuItems
          //console.log props from the MenuItems
          //console.log props from the MenuItems
         //console.log props from the MenuItems
            console.log(props.ema);

          })
          .catch((error) => {
            console.log(error);
          })
        },[]);

//final delete of profile
      const deleteButton = id => {
        axios.delete('http://localhost:5000/users/status/'+id, { headers:
          {
          "this-token": localStorage.getItem("this-token")
        }
        })
          .then(res => console.log(res.data));
          setStatusCon(statusCon.filter(el => el._id !== id));
      }

//show delete profile button
      const showDeleteAction = () => {
          setShowDelete(true);
        }
      //display gift give button
            const showGiftButton = (entry) => {

        showGiftAction || '' ? setShowGift(false) : setShowGift(true);



              const giftId = statusCon.filter(el => el.ourId === entry);
              for (let i = 0; i < giftId.length; i++ ) {
                if (!showGiftAction) {
                let cool = document.getElementsByClassName(entry);
                  cool[i].style.display = "inline-block";

               } else {

                 let cool = document.getElementsByClassName(entry);
                 cool[i].style.display = "none";


                   setGifted('');

               }

               }

}



      //updateSend
        const statSend = async (our) => {


           const gifter = {
                ourIdMan: our,
                weReady: "successfully gifted"
              }

             await axios.put('http://localhost:5000/users/upStatsend', gifter, { headers:
               {
               "this-token": localStorage.getItem("this-token")
             }
             })
             .then(res => {
                  window.location = "/status";
                })
                .catch((error) => {
                  console.log("big problem");
                })
      }

            const updateAd = async (him, our) => {

             const adUp = {
                oldEmail: our,
                newEmail: him,
                adCart: statusCon
              }

          await axios.put('http://localhost:5000/users/adminup', adUp, { headers:
               {
               "this-token": localStorage.getItem("this-token")
             }
             })
             .then(response => {
                  console.log("greetings from below");
             })
             .then(res => {
                  statSend(our);
                  console.log("tumbleweed");
                })
                .catch((error) => {
                  console.log(error);
                })


  }


       const sendGift = async (him, our) => {
        /* let b = our;
         let c = b.indexOf(".com");
         let d = b.substring(0, c !== -1 ? c : b.length);*/

         let bb = him;
         let cc = bb.indexOf("@");
         let dd = bb.substring(0, cc !== -1 ? cc : bb.length);

         const answer = {
           commId: our,
           email: him,
           ready: `Hey ${dd}, you've been sent an order!`
         }


        await axios.post('http://localhost:5000/users/sendGift', answer, { headers:
         {
         "this-token": localStorage.getItem("this-token")
       }
       })
       .then((res) => {
            updateAd(him, our);
            console.log(res.data);
          })
          .catch((error) => {
            console.log(error);
          })
          setShowGift(our);
            console.log(answer.commId);
          }



  const giftedName = e => {
        setGifted(e.target.value);
          }

      const closeDelete = () => {
        setShowDelete(false);
        }

  const accountDelete = async () => {
    const here = { headers:
      {
      "this-token": localStorage.getItem("this-token")
    }
  }
  await axios.delete('http://localhost:5000/users/account', here)
    .then(response => {
          console.log("that's nice");
         })
        .catch((error) => {
          console.log(error);
        })
        axios.delete('http://localhost:5000/users/logout', here)
        .then(response => {
          const good = localStorage.clear('this-token');
            window.location = 'http://localhost:5000/login';
        })





}

    const displayOrder = id => {
       window.location = '/displayOrder/'+id;
    }

    const ordersList = () => {

       return statusCon.map(sl=> {
         return <LilStat
         status={sl}
         displayOrder={displayOrder}
          deleteButton={deleteButton}
         tisGift={showGiftButton}
          gifted={giftedAction}
          sendGift={sendGift}
          showGift={showGiftAction}
          forGift={giftedAction}
         giftedName={giftedName}
         key={sl._id}/>;
      })
    }








    return (

      <div>
      { (showDelete === false) ?
    <EditRun showDelete={showDeleteAction}/>
      :
      <DeleteRun closeDelete={closeDelete} accountDelete={accountDelete}/>
    }
      <h2
      className="shadow p-1 mb-4"
      style={{
        marginTop: "3%",
        fontFamily: "georgia",
        color: " grey",
        fontSize: "35px",
        letterSpacing: "2px",
        backgroundColor: "",
        textAlign: "center",
        border: "solid",
        borderWidth: "1px",
        borderRadius: "5px"

    }}>Profile</h2>
          <div>
          { ordersList() }
      </div>


        </div>


    )
  }
export default StatLine;

6 Answers

Rohald van Merode
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree
Rohald van Merode
Treehouse Staff

Hi Killeon Patterson 👋

Could you please elaborate on your question or comment? I'm unfamiliar with this code, is this part of one of our courses? If so could you please share a link to it?

Killeon Patterson
Killeon Patterson
18,528 Points

-Hello Rohald van Merode. The lesson is a React lesson. This code is my sandbox where I workout with the lessons. I was able to do it in the challenge, but having issue duplicating outside of a quiz.

I'm attempting to pass props from the MenuItems component via the "emailList()" function, to the StatLine component. When I try to console.log() the props in the StatLine component, it returns undefined. Do you have any insight to why? Thank you for your time.

Rohald van Merode
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree
Rohald van Merode
Treehouse Staff

Hi Killeon Patterson,

It's hard to tell without seeing your code in it's entirety but I notice two things in the snippets you've shared. In your MenuItems component you're calling the this.usersList() method in the render method while this doesn't seem to be available in this component. Another thing I noticed is that where you return the StatLine component you're passing in the prop ema with the userEmail.email while you're trying to log this.props.emailArray instead.

I hope this is helpful, if not please share a link to your code (through either a workspace snapshot or a Github repo) and I'd be happy to have another look 🙂

Killeon Patterson
Killeon Patterson
18,528 Points
  • Hello Rohald van Merode

My apologies, I thought a snippet would be less to look at. Although, I have now updated the code for better context. I'm able to console log the array before returning it, in the StatLine component, but it still returns "undefined" when I attempt to console log the props in the component. Thank you for you time and insight.

Rohald van Merode
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree
Rohald van Merode
Treehouse Staff

Hi Killeon Patterson,

Thanks for providing some more context! It's hard to tell what is causing this issue by just looking at lines of code. I've had a look at it but I'm just not able to tell you what the issue is for certain. As mentioned in my previous comment sharing a link to your code through either Workspaces or Github would be great as that would give us a complete overlook (components / imports / dependancies) as well as give us the opportunity to play around with it to figure out what is going on and give you better pointers in how to find the solution.

That being said my best guess at this point would be that your component is being rendered before the data has been fetched. You could try to add a conditional in your emailList method that checks if there is anything in the users state before returning the component. Something like so:

emailList() {
     return this.state.users ? this.state.users.map(userEmail => {
       return <StatLine ema={userEmail.email}/>;
       } : ""
  }

Another way would be to initialise your users state to have some empty content instead of it just being an empty array. For example if you put a user object in that array containing all the properties it should have after it has been fetched with initial values of empty strings. This way if the component gets rendered userEmail.email would just be an empty string instead of throwing an undefined error (component will then be rerendered as soon as the data does become available).

this.state = {
      users: [{
           name: '',
           email: '',
           < etc. >
      }]
};

Hope this helps to get you going again 🙂

Killeon Patterson
Killeon Patterson
18,528 Points
  • Rohald van Merode

That makes sense! My mistake for the misunderstanding. Here is a link to the full project. https://github.com/Kilosince/Udated-Pro

I did attempt to put a conditional in the emailList function. From what I could tell, it continued to return "undefined" in the desired component. The same appeared to be true for the initializing a new state. I appreciate any further insight on this issue. Thank you.

Rohald van Merode
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree
Rohald van Merode
Treehouse Staff

Hi Killeon Patterson,

I just downloaded your repo and got everything working on my end. But where is it exactly you're trying to render the StatLine component to the DOM? I see the /status route but you're not passing in any props through that route. In the user.bank.component.js file you're only calling the emailList method inside the usersList method but this component never gets rendered. I'm not sure what you're trying to accomplish but you could call the emailList method in the same way as you've done with the usersList on line 85, this way the component ends up in the render method and will be shown on the page (as well as the ema prop being logged to the console)

Hope this answers your question and fixes your issue 🙂

Killeon Patterson
Killeon Patterson
18,528 Points
  • Rohald van Merode

There is a sendGift() function in the StatLine component. The function is meant to send data to another user. If the function is successful in delivering the data to the -receiver-, the -sender's- data will also be updated with a message of "successfully gifted" being displayed on their profile.

Currently, the function display's "successfully gifted" even when the data was not received by the intended user. The function relies on user's email to resolve itself. My plan to fix this bug was to check against an array of all of the user's emails before sending the data to the -post- route. This way the function could error before any more calls were made.

I initially planned to make another call to the server in the sendGift() function to: retrieve the email data from the route, put it in an array, and check it against the -sender's- input. "But maybe that's too many calls to the server." My understanding of React was since I've already got the necessary data (emails) from a route used in the MenuItems component, that I'd be able to map through that data, put it in an array and pass it as props to the StatLine component.

That's what my question to you was regarding. I had not attempted rendering this data because I was having trouble passing it as a prop. I was trying to console.log() the data before I tried rendering, to prove that it was there. I've passed plenty information to components throughout this sandbox app. But now, I'm experiencing issues when I try it outside of the lesson. Specifically, in this current attempt. Thank you for your effort. I guess I'll just keep searching : )

In theory though, is my understanding of React correct? Shouldn't I be able to pass an array as props and not have to go get it from the server in a new call?