0

To set some context: I have an API that returns an array of key/value pairs. I want to add a feature that displays each Key/Value on the webpage when it loads (done) and implement a "Search" on this list using a text box, where as users type, the list shrinks to only matching keys.

Relevant React code looks as follows:

var PropEntry = function PropEntry(p) {    
    var displayValue = React.createElement(
        "span",
        null,
        p.value
    );
    var valueMarkup = React.createElement(
        "div",
        null,
        React.createElement(
            "span",
            { className: "prop-value" },
            displayValue
        );
    return React.createElement(
        "div",
        { className: "prop-entry" },
        React.createElement(
            "label",
            null,
            p.name
        ),
        valueMarkup
    );
};

var ColsView = function ColsView(props) {
    var cols = props.streamCols;
    return React.createElement(
        "div",
        { className: "named-container" }, 
        React.createElement(
        "input",
        { type: "text", placeholder: "Search", onChange: <CallFunctionHere> }),
        React.createElement(
        "div",
        { className: "named-entries" },
        cols.map(function (col) {               
            return React.createElement(PropEntry, { name: col.Name, value: col.value });
        })
        )
    )
}

ColsView = ReactRedux.connect(function (state) {
    return { streamCols: state.streamCols };
})(ColsView);

I'm trying to add a textbox just above the list that filters this list as users type (onChange keystroke). What would be the best way to do this? I would like to avoid calling the API another time since I already have the full list of items.

I should also mention that I'm very much a beginner with React and I'm just trying to add features to an existing .js file that I do not wish to rewrite completely :)

4
  • Your question is unfortunately very open-ended/broad. There are many, many ways of implementing client-side search. The most basic one would be to filter the values down using a regex. Something like values.filter(value => value.match(/<some regex>/g)) The some regex could naively be the value you are trying to filter by, but it's easy to get more complicated than that very quickly. On the way more complicated side of things, you can do things such as tokenization and building search trees, all of which are their own massive topics. Commented Sep 24, 2018 at 20:36
  • Hi @MatthewHerbst, sorry for the confusion, my question is very basic - I'm basically just trying to figure out where I can add the onChange function on the textbox and how I can get the values that are already part of the various "divs" and hide a few of them (ones that don't pass the filter). The actual "filtering" using the regex comes later. Commented Sep 24, 2018 at 21:07
  • Not sure I follow - I don't see a textbox, or any type of input for that matter, in your code. Commented Sep 25, 2018 at 2:03
  • Hi @MatthewHerbst , apologies - I didn't add the textbox input part because I wasn't sure if I had it in the right place originally. I've edited the question to include the text box now, would really appreciate any thoughts! Commented Sep 26, 2018 at 18:13

1 Answer 1

1

You seem pretty close!

As part of your class, define a callback that can be used to handle the click:

handleChange = (event) => {
  // Get the value from the event
  const searchValue = event.target.value;

  // Save it to state
  this.setState({ searchValue });
}

You should update the definition of the search box to pull its value from the state so that React doesn't wipe out the value if the component re-renders:

React.createElement(
  "input",
  {
    type: "text",
    value: this.state.searchValue;
    placeholder: "Search",
    // Note that we just pass the function here, we don't actually call it.
    // React will call it for us when an onchange event occurs for this element
    onChange: this.handleChange,
  }
);

Now, in your render method, you can do the filter based on the value saved in state:

const regex = new RegExp(this.state.searchValue);
const filteredCols = Object.keys(cols)
  .filter(key => key.match(regex))
  .reduce((filtered, key) => {
    filtered[key] = cols[key];
    return filtered;
  }, {});

filteredCols.map(function (col) {               
  return React.createElement(PropEntry, { name: col.Name, value: col.value });
});

As we've both noted, the regex probably won't be that simple (it's an exact match right now) but that can be dealt with in another question if needed.

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

2 Comments

Perfect, that makes a lot of sense! Thank you @MatthewHerbst :) PS - there's a small typo in the answer (click instead of change), just thought I'd let you know
Thanks for catching that, fixed!

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.