React Semantic UI Search Component not updating main page

UPDATE: GOT IT! Maybe I should search a little longer before posting Qs, but sometimes writing the Q helps me find the issue. In this case I was loading the data from the DB in the topics page, instead of receiving state from the App.

What’s happening: I have a React app with a search input in navbar. The serach function is working as I intended. The functions are props passed from App , the top level component.

However when the state is updated the Main page which is routed to Topics doesn’t change.

to reproduce:
https://emquick.herokuapp.com/topics
Click on topics
Type in search
if you open the console log while typing in the seach bar (try typing “heart”) you can see the serach is working, but the topics page doesn’t change.

how do I send the filtered search from App through the router to the topics page?

Source here:
https://github.com/AdventureBear/emquick

(look in src folder for these files
App.js
/navigation/Navbar.js
/topics/Topics.js

UPDATE: When I use chrome’s devtools with the React tools, I can see that the APP state contains just the resource from the search, bu the Topics state still contains the original four.

Why doesn’t updating state in the App pass down to the Topics component? Can I get it to rerender? Is this a react router issue?

When something like this happens, you can often trace the problem by logging to the console in the lifecycle methods of a component.

In this case, since you are expecting that props should be passed into the Topics component, one of the first things I would check is (instead of the filter function):

// Topics.js

componentWillReceiveProps() {
  console.log('componentWillReceiveProps in Topics', this.props.resources);
}

And you should see the props updating as you intend it to.

The problem turns out to be this:

// Topics.js

const resources = this.state.resources; // Should be this.props instead of this.state

There is also another incorrect reference here:

// Topics.js
const ThisTopic = (props) => {
  return (
    <Topic resources={this.state.resources}
      {...props}
    />
  )
}

When building larger projects, I think it’s often a good idea to write tests. It does take a lot longer to build something, but it will potentially save you time when issues come up (and everyone else’s time if you are working with others) if you write the right tests. For example, if you had written a test to make sure that props passed in are being rendered properly, the time spent on finding the issue would probably have been only a few minutes at best.

Jest + enzyme’s (just a personal preference, there are other tools for testing) doesn’t have a very high learning curve if you want to become productive with them, you may want to have a look into that. I hope that helps! :smile:

EDIT: I forgot to mention that the componentWillMount() method is only executed once before the first render of the component, that’s why you are seeing the list but nothing else happens when you run it again. Also, the Topics component doesn’t need its own state because, as far as I can tell, it’s there purely to present results. You can get rid of states inside this component completely because that’s an added, unnecessary complexity, and have it only react to props.

1 Like

thank you! I had identified the main issue (this.state not this.props), however the additional information you provided is very helpful.

I’ve been struggling to learn testing as well, and I would like to learn.

Would you be able to show me an example of a test for the Topics.js component like you described?

I’m glad that it helped!

If you are struggling to learn to write tests, I recommend writing tests in a less complex environment first—the issue (at least for myself) is that there is a lot happening when you write tests for React component; if you are missing just a bit of fundamentals (read, myself), you’ll end up down a rabbit hole trying to figure out why things are not working instead of the tests doing work for you.

Back to the Topics component, one test I would write is this (not tested, no pun intended!):

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { shallow } from 'enzyme';

it('should correctly render the resources prop', () => {
  // Create props to be passed into the component so that you know
  // what outcome to expect
  const testResources = [{ name: "heart" }, { name: "hearthstone" }];
  // Use enzyme to shallow render a comopnent for testing
  const wrapper = shallow(<Topics resources={testResources} />);
  // Find the list of list items
  const listItems = wrapper.find('li');
  // Get the strings rendered to the <li>'s
  const listItemHeart = listItems.get(0);
  const listItemHearthstone = listItems.get(1);

  expect(listItemHeart.props.text()).toEqual("heart");
  expect(listItemHearthstone.props.text()).toEqual("hearthstone");
});

The thing that I struggle with (and still do) is determining what tests should not be written. The advantage of consciously writing stateful and stateless components is that, in terms of testing, the mental model for stateless components is that they are mostly (purely?) intended for presentation purposes—so as long as you have tested the output to be correct (after taking into account edge cases), then the component is… working as intended!

For example, the Topics component doesn’t care whether a list is filtered or not (and it shouldn’t), it also doesn’t care about whether an event has triggered to change anything or not (and, again, it shouldn’t). These are probably obvious things to most people, but consciously keeping these things in mind, in my opinion, helps to get over that hurdle at the beginning.

Testing HOCs, event handlers… etc. is a bit more involved, so if you don’t feel comfortable with testing yet, just focus on what you can comfortable write first—when you are learning, it’s never too late to come back to add tests. I hope that helps! :smile:

1 Like

that’s great and helpful feedback!

As this useful app grows I’m going to quickly need some design changes too, so while not related to the reason for my post, if you have suggestions for making it have a better appearance and more user friendly, feel free to comment on that as well.

And I do appreaciate the feedback on the code as well. Some is a bit sloppy for sure.

I’ll start incorporating testing as I go along, probably with an easier project first.

To be honest, and given what it’s meant to do, I actually rather like the aesthetics; not least because I’m rather fond of minimalist designs. The only comment I have is perhaps come up with a colour palette for when you have more content—for example, in the HEART Score section, I think it would be great to use colours to indicate severity, having consistent visual queues for making choices quickly built into your app would probably help with those who working in an ER. For choices that are not ranked, I think it’s best not to colour them or use something like light grey.

Continuing with the example, the placement and size of things are also important when you are working in such a stressful environment. In particular, I think the font size of the score should be larger; also, I personally think that you should apply bold to the actual score but not the string before it to give it the right emphasis (a friend from my previous job taught me that):

Score: 2

I think applying font-variant: small-caps; to “Score” may make the number stand out even more. Also, I think the score should be placed above the questions to place more attention (the first time I played with it I completely missed the score, that’s just me though!).

Incorporating animation will be a lot more work but I think it will also be rewarding. Using the same example as above, I think the score can also be displayed according to a (or the same) colour scheme to indicate severity— that way you can use CSS transitions to easily indicate something has changed (in this case colour) as you go through the questions. There is quite a bit of logic to wire up for this one, though, and it’s not as high of a priority as the one mentioned above.

Coming back to the tests—don’t stress too much about it for now, it can be incrementally added so you can learn as you go. If you want to get into the habbit of writing non-sloopy code, you may want to invest some time in tweaking (or add one if you’re not already using one) the linter in your code editor. You could also consider something like TypeScript in the future (I should have mentioned this earlier) when you have time to work through some potential headaches (it may be really weird at the beginning, particularly when you are using it with React because just about everything you do would throw a linting error)—it will catch a lot of errors as you code.

I hope that helps!

EDIT: P.S. Sorry! The only comment turned into lots of comments! d:

1 Like

No worries , I appreciate everything!

All good! It’s fun for me, too! Good luck with the project :slight_smile: