0

I'm creating a status icon based on whether an object has a certain amount of errors.

What's the best way to pass the data from ComponentDidMount to the function I want to evaluate the data in. I'm attempting to add up the status in an object, but getting TypeError: error.filter is not a function

import React from 'react';

class PolicyIcon extends React.Component {
  state = {
    errors: ''
  };

  componentDidMount() {
    let initialErrors = [];
    fetch('http://localhost:3000/status/2/errors')
      .then(response => {
        return response.json();
      })
      .then(data => {
        console.log(data);
        this.setState({ errors: data });
      });
  }

  addErrors = errors => {
    console.log(errors);
    errors.filter((x, i) => {
      return x.isError >= 5;
    }).length;
  };

  statusCircle = errors => {
    return this.addErrors(errors) ? (
      <svg height="100" width="100">
        <circle
          cx="50"
          cy="50"
          r="40"
          stroke="black"
          stroke-width="3"
          fill="red"
        />
      </svg>
    ) : (
      <svg height="100" width="100">
        <circle
          cx="50"
          cy="50"
          r="40"
          stroke="black"
          stroke-width="3"
          fill="green"
        />
      </svg>
    );
  };

  render() {
    <div>{this.statusCircle(this.state.errors)}</div>;
  }
}

export default UserIcon;

2
  • You save the conditions in the state, so you don't need to pass them. You just use this.state.conditions. Also in render you have <statusCircle />, but 'statusCircle' is a function, not a component. Should have it as <div>{this.statusCircle()}</div>. (P.S. don't forget, at the moment you don't have a default state, so 'this.state.conditions' will be undefined until you set it in the API call) Commented Apr 15, 2018 at 23:34
  • @Jayce444 Thanks for the input, based on what you said I made some changes and updated the question. I'm getting some more errors but is it looking better now? Commented Apr 15, 2018 at 23:55

1 Answer 1

2

There is a lot of advice that I can give you with this code. Firstly, you are coupling your code very hard. Meaning, you are giving your icons so much task to conduct. It is responsible data retrieval and defining the UI. Below I have laid out a way for you to do what you want and a very neat structure as well.

const UserIcon = ({state}) => (
 <svg height="100" width="100">
  <circle
    cx="50"
    cy="50"
    r="40"
    stroke="black"
    stroke-width="3"
    fill="{state === 'error' ? 'red' : 'green'}"
  />
 </svg>
);

As you can see, the UserIcon is solely responsible for the user display. Now, we should write a separate class based component that will do the fetching and data manipulation.

class UserIconManager extends React.Component {
 constructor(props){
  super(props);
  this.state = { errors: 0, loaded: false }
 }

 componentDidMount() {
  fetch('http://localhost:3000/user/2/status')
  .then(response => response.json())
  .then(data => this.setState({ errors: data.errors, loaded: true})
 }

 render() {
   const { errors, loaded } = this.state;
   const iconState = errors >= 5 ? 'error': null
   return loaded ? 
    <UserIcon state={iconState} /> :
    null
 }
}

I am not sure about the specifics of what you are trying to do but im pretty sure my example is 100% relevant. Best of luck

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for this answer, it looks much simpler. However, I don't see where you are counting up the errors, am I missing it? What is loading doing? Also I am getting two errors with this: UserIconManaager.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
In the UserIconManager render, he has const iconState = errors >= 5 ? 'error': null, that's where he checks if there are 5 or more errors. Also for that error, in the UserIconManager render, change the return to return loaded ? <UserIcon state={iconState} /> : null
whoops didnt expect you to just directly paste my code. I was programming straight from memory off my pc. I changed the line to return null if the data was not fetched yet. I improvised with the loading variable. basically no icon will show up till you get your data back.
I think it's worth noting that using componentWillMount to handle side effect like querying API is not recommended by React itself: reactjs.org/docs/react-component.html#unsafe_componentwillmount, aslo componentWillMount has been planned to be deprecated and will become UNSAFE_componentWillMount since React 17. The API fetching should be done insde componentDidMount instead.
@ThaiDuongTran I agree. its been changed

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.