React Searchable Navigation Bar

Internship Xiao Bai really wrote the front end for the first time, used React for the first time, took notes while writing the project, and used the components of SAP UI5 in the final code. Forgive me that direct copy does not work.
Also, I can't show highlights here directly in jsx format, so I use js format directly

1. Basic Structure

We want to build a searchable sidebar like the one shown, and enter keywords in search to filter the data shown below

We can define a LeftSide component that contains MySearchInput and MySideNav components to receive input and display keyword filtered data, respectively

2. Preparatory knowledge

We need prep-knowledge of local data and data transfer between components in react

1. Fetch for data reading

First we get the json data locally, rather than using jQuery with React, we get the data locally or remotely using the encapsulated fetch function, with the following code

fetch(
    './data/XXX/XXX.json'
  )
    .then(res => res.json())
    .then(data => {
      console.log(data)
      
    })
    .catch(e => console.log('error:', e))

The only thing worth noting here is that. /denotes the public/directory, which is the directory where index.hml is located

Note the difference from the import path in the js file, where. /represents src/directory

2. props and state for data transfer

The main components responsible for data transfer are props and state.

props

We can think of props as a const parameter passed into a function.

function Component(props) {
    return <h1>I have a prop1: {props.prop1}!</h1>;
}
 
const element = <Component name="c1" prop1="propValue"/>;

As an example, we pass in two values, c1 and propValue, to a Component in which we can access these two values using this.props.name and this.props.prop1, which we call the properties of a Component Component (props)

function access without adding this

It is worth noting that props cannot be changed in components, that is, even if you change it, it will have no effect (unless)

More props operations are detailed in -props property of React series

state

Contrasting props, we can think of a state as a variable in a class (different from the normal class variable this.a).

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date(),
                  a:10,
                  b:this.props.b
                 };
  }
 
  render() {
    return (
        
      <div>
        <h1>Hello, world!</h1>
        <h2>Now is {this.state.date.toLocaleTimeString()}.</h2>
        <h3> {this.state.a} </h3>
      </div>
    );
  }
}

As an example, we created a state called date in the constructor and accessed it using this.state.date (where the date state is a class and not simple data)

State differs from props in more than just the way it is initialized. When we use **this.setState to modify the state in a component, it will automatically re-render **

this.setState({a:this.state.a+1})

If you execute the above code, the 10 displayed on the web page will become 11

Note that the constructor of a class is called only at creation time, and that this.state.b, which is assigned only in the constructor, remains unchanged when the parent passes in this.props.b changes

See in detail Props for React and the difference from state

Props for React and the difference from state It is mentioned in the article that stateless components (i.e. components without states) should be used whenever possible instead of stateful components

Downward Flow Data and State Promotion

From the description above, we know that props can only be passed in by parent to child components, so it is called downflow data, and state can only record state in the current component

Direct use of props and States does not seem to complete data transfer between child and parent or sibling components.

But with callback functions, we can do this in a way called state elevation

For example, we have a parent component, Base, and a child component, Child. We get data from Child by user input. Our goal is to pass data into Base

First we set the state this.state.data (not required) and a function handleData (required) to modify/pass the data in Base, and pass the handleData function to Child through props. When Child gets the data, the handleData function of the parent component is called through certain events (such as clicking on the onClick event)., successfully passed data to Base

In Child, we can also set a class variable or state to store data for convenient function calls. If the subcomponents get data through the input component, we can also process e.target.value directly with E as a parameter.

Function arguments require a.bind(this, parameter) way of binding, as detailed in How the onClick function of React passes parameters We can also set up another jumper function in our component, handleData, to call handleData directly in _handleData

Introduction to Official Website

React Learning: Example of State Promotion

About e.target

3. refs for data transfer

I have not tested this way

If you find the above state improvement more difficult, we can use another new concept, refs

Refs can be used to access Dom nodes in render() (React does not recommend getting DOM nodes directly from document.getElementById("xxx"), which is commonly used in control input/video/audio scenarios (but be careful not to abuse refs)

There are three ways to use refs, and here we will only describe one of them, React.createRef(), and the other two are detailed in Summary React(3):state, props, Refs

After v16.3, we can use React.createRef() to create a series of refs for the parent component, get the child component in render() in a similar way to assigning attributes, and then access it in the parent component. The sample code is as follows

import React from 'react';
class TextInput extends React.Component {
    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
        // Create Refs through React.createRef();
        this.textInput = React.createRef();
    }
    handleClick() {
        // Access Dom nodes through this.textInput.current
        this.textInput.current.focus();
        console.log(this.textInput.current.value)
    }
    render() {
        return (
            <div>
                <input type="text" ref={this.textInput} />
                <input
                    type="button"
                    value="Click on my input box to get focus"
                    onClick={this.handleClick}
                />
            </div>
        );
    }
}
export default TextInput;

3. Specific Codes

!! I use sap ui5 Part of the components in the, do not affect reading, when you use the corresponding components directly replace the line

LeftSide

Parent component, where this.props._handleClick is the parent component of LeftSide used to handle clicks in the list, ignored here

class LeftSide extends React.Component {
  constructor(props) {
    super(props);
    this.version = props.version;
    this.state = {
      search_key: ""
    }
  }

  handleInput(e) {
    console.log(e.target.value)
    this.setState({
      search_key: e.target.value
    })
  }

  render() {  
    return (
      <div className='leftPage' >
        <div className='searchInput'><MySearchInput changeInput={(e) => this.handleInput(e)} /></div>
        <div className='sideNav'><MySideNav searchKey={this.state.search_key} _handleClick={this.props._handleClick} /></div>
      </div>
    )
  }

  shouldComponentUpdate() {
    return true;
  }
}

MySearchInput

Processing user input, changing the data transfer to the parent component in real time (we can also use _onSearch to transfer on click)

class MySearchInput extends React.Component {
  constructor(props) {
    super(props);
    this._onChange = props.changeInput;
    this.state = {
      key: ""
    }
  }
    
  _onSearch(evt) {
    console.log("Final:")
    console.log(this.props.value)
  }

  render() {
    let _onChange = this.props.changeInput;
    return (
      <FormItem>
        <InputGroup
          actions
          inputValue={this.state.value}
          onChange={_onChange}
        >
          <Button
            glyph="search"
            option="light"
            onClick={this._onSearch.bind(this)}
          />
        </InputGroup>
      </FormItem>

    )
  }
}

MySideNav

Implement real-time search (output when searchKey is empty or matches)

class MySideNav extends React.Component {
  constructor(props) {
    super(props);
    this.cate_map =
      {
        "Type1": {
          "items": [[]]
        }
      }  //json data structure
    this.loadJson(); //Loading data
    console.log("sonstructor done")
  }

  loadJson() {
    let cate_path = './data.json';
    fetch(
      cate_path
    )
      .then(res => res.json())
      .then(data => {
        console.log("from loadJson")
        this.cate_map = data; //Direct assignment
      })
      .catch(e => console.log('error:', e))
    this.setState({
        update:""
    })//Because of asynchronous, re-rendering is required after loading is complete
  }

  handleClick(keywordID) {
    console.log("from handleClick")
    console.log(keywordID)
    this.props._handleClick(keywordID)  //Processing list clicks, ignored here
  }


  render() {
    console.log("render")
    
    console.log("log from NAVI")
    console.log(this.props.searchKey)

    let ct_list = this.cate_map.ComplexType
    let complexType_list = [];
    
    for (let index in ct_list.items) {
      let itemName = ct_list.items[index][1];
      if (this.props.searchKey == "" || itemName.indexOf(this.props.searchKey) != -1)
        complexType_list.push(<SideNav.ListItem id={ct_list.items[index][0]} name={itemName} onClick={this.handleClick.bind(this, ct_list.items[index][0])} url="#" />)

    }
    return (
      <SideNav selectedID="SideNav">
        <SideNav.List>
          <SideNav.ListItem
            id="Type1"
            name="Type1"
            url="#">
            <SideNav.List>
              {complexType_list}
            </SideNav.List>
          </SideNav.ListItem>
        </SideNav.List>
      </SideNav>
    )
  }
}

Keywords: React JSON JQuery

Added by rigi2 on Mon, 12 Aug 2019 06:01:38 +0300