preface

The recent tests have given me fewer bugs, and my colleagues in codeReview have rarely pointed out that I wrote the wrong thing

On the contrary, I put forward higher requirements for the design of the overall file structure and the composition structure and state of components. I have to say that my code level has been improved, indicating that there is still a lot of room for progress in the process of steady improvement

But when I see my colleagues tell me how the whole component can be separated to improve maintainability and reusability, others can see the logic of this part more clearly

At that time, I wondered why my colleague could have such an opinion. Was it just because he had more experience and thought more deeply than ME? My gut tells me it’s not that simple.

I was thinking about how to figure out how to divide the logic of this business and how to design the data structure I wanted when I saw the design drawings. Suddenly, I remembered the React philosophy concept that I glanced at and then slipped by when I first learned React

I immediately went to the official website to look at the concept, and sure enough, I did not know how to prove the design structure and state of a component before, and the state of these components could not be verified after it was written. In addition, I would almost request data for each sub-component, and define a state for some data that I wanted to display to solve the problem in a simple and rude way

When writing a module is almost as soon as I begin to write, often without any thinking and design is just the thought of to write what you, just want to quickly finish function, so that write many filleted unreasonable code let I tread many pits, harvest a lot of bugs, components before see, my first idea is to refactor.

Having said so much about my history of blood and tears, let’s take a look at what React philosophy actually says, how it solves my pain points mentioned above, and what I have learned from it.

Preparation stage

First of all, before we write the code, there will be something. One is the product design diagram of PM, and the other is the JSON data returned by students at the back end

[
  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}];Copy the code

To understand such a simple product design contains what are the demand, this is a list of displaying products, users can in to a keyword search of goods, and by clicking on the check box to choose whether to show the spot, list contains is name and price of products, product support, according to the classification of running out of goods is called red.

Once we have a basic understanding of the requirements represented in the product diagram, we can begin the first step in coding

Divide the component hierarchy by product diagram

At the beginning, when you are not familiar with the division, you can draw a box on the product design draft to determine the component and sub-components. You can consider the component as a function or object. The component also follows the single function principle, that is, a component is responsible for only one function

At the same time, a good JSON data model should correspond to components one to one, with components matching some part of the data model

Different colors are divided into different components, which can be divided into five parts:

  1. FilterableProductTable (orange): the entire sample application as a whole
  2. SearchBar(blue) :Accept allUser input
  3. ProductTable(green) :showThe data contentAnd according to theUser inputScreening results
  4. ProductCategoryRow(Sky blue):For each oneProduct categoryShow the title
  5. ProductRow(red) :Each line shows oneproduct

The name of the component should give you a quick idea of what the component is written on. (I have to say that my previous component names were really bad. After a few days, I would look back and feel confused

Hierarchy of components:

  • FilterableProductTable
    • SearchBar
    • ProductTable
      • ProductCategoryRow
      • ProductRow

withReactBuilding static pages

After we have divided the component hierarchy, we can write the code. First, we use the existing data model to write a UI rendering without interaction. This is because UI rendering requires more code and interaction requires more details to be considered

The parent component passes the data layer by layer. This is also a characteristic of React, which is one-way data flow. In this process, state is not used first, because state represents changes with time, so it is used in the process of interaction

When building applications, you can use a top-down or top-down approach. Top-down means to write the highest level components first, such as FilterableProductTable, which is suitable for simple applications. Bottom-up means that the lowest level components, such as the ProductRow component, are written first. This approach is more suitable for large application builds

const PRODUCTS = [
  {category: 'Sporting Goods'.price: '$49.99'.stocked: true.name: 'Football'},
  {category: 'Sporting Goods'.price: '$9.99'.stocked: true.name: 'Baseball'},
  {category: 'Sporting Goods'.price: '$29.99'.stocked: false.name: 'Basketball'},
  {category: 'Electronics'.price: '$99.99'.stocked: true.name: 'iPod Touch'},
  {category: 'Electronics'.price: '$399.99'.stocked: false.name: 'iPhone 5'},
  {category: 'Electronics'.price: '$199.99'.stocked: true.name: 'Nexus 7'}];const FilterableProductTable = () = > (
  <div>
    <SearchBar />
    <ProductTable products={PRODUCTS} />
  </div>
);

const SearchBar = () = > (
  <form>
    <input type="text" placeholder="Search..." />
    <p>
      <input type="checkbox" /> Only show products in stock
    </p>
  </form>
);

const ProductTable = ({ products }) = > {
  const rows = [];
  let lastCategory = null;

  products.forEach((product) = > {
    if(product.category ! == lastCategory) { rows.push(<ProductCategoryRow
          category={product.category}
          key={product.category}
        />
      );
      rows.push(<ProductRow product={product} key={product.name} />);
    }
    lastCategory = product.category;
  });

  return (
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>{rows}</tbody>
    </table>
  );
};

const ProductCategoryRow = ({ category }) = > (
  <tr>
    <td colSpan="2">{category}</td>
  </tr>
);

const ProductRow = ({ product }) = > {
  const name = product.stocked ? (
    product.name
  ) : (
    <span style={{ color: "red}} ">{product.name}</span>
  );

  return (
    <tr>
      <td>{name}</td>
      <td>{product.price}</td>
    </tr>
  );
};

Copy the code

determinestateThe smallest complete set of

When we have some other data that triggers changes to the underlying data and gives the UI an interactive result, we can use state in React

The smallest and complete representation is that we can first find all the data that will change according to time, and then select the most necessary data as state from these data, and the other data can be obtained by calculation.

Take a look at what data the current application has:

  • Raw data on goods
  • User’s search data
  • Check box Indicates whether the value is selected
  • Filtered data

Here are some questions to ask yourself before deciding whether the data is state

  • Whether the data can passpropS to pass
  • Will change through time
  • Whether can pass otherstatepropsTo calculate the

So finally we can confirm that the raw data can be passed by props, that the user-searched data and the checkbox value can be used as state, and that the filtered data can be calculated from the raw data and the user-searched data and the checkbox data. So the final state could be:

  • User’s search data
  • Check box Indicates whether the value is selected

determinestatePlacement position

Once the minimum set of states has been determined, the next step is to determine which component the state should be placed in

We know that React is a one-way flow of data, flowing from top to bottom, so we should write states in the co-owner (that is, the co-parent of the component that needs these states).

We can see that the ProductRow component needs filtered data, the SearchBar component needs search data and check box values, so we can put state in their co-owner component, FilterableProductTable. Passes the state using props

Add reverse data flow

When we want to change a higher-level component from a lower-level component, we need to reverse the data flow

The reverse flow of data in React is done by requiring the higher-level component to pass the method (the callback function) that changes state to the lower-level component using props. The child component’s changed state value is passed to the callback function.

In order to get the latest state in the current application, FilterableProductTable must pass a callback function that triggers the state change to SearchBar. We can use the onChange event of the input box to monitor changes to the user input and notify the callback function that FilterableProductTable passes to the SearchBar.

const FilterableProductTable = () = > {
  const [filterText, setFilterText] = React.useState("");
  const [inStockOnly, setInStockOnly] = React.useState(false);

  return (
    <div>
      <SearchBar
        filterText={filterText}
        setFilterText={setFilterText}
        inStockOnly={inStockOnly}
        setInStockOnly={setInStockOnly}
      />
      <ProductTable
        products={PRODUCTS}
        inStockOnly={inStockOnly}
        filterText={filterText}
      />
    </div>
  );
};

const SearchBar = ({ filterText, setFilterText, inStockOnly, setInStockOnly, }) = > {
  const handleProductsSearch = (value) = > {
    setFilterText(value);
  };

  const handleStockCheck = (value) = > {
    setInStockOnly(value);
  };

  return (
    <form>
      <input
        type="text"
        placeholder="Search..."
        value={filterText}
        onChange={handleProductsSearch}
      />
      <p>
        <input
          type="checkbox"
          value={inStockOnly}
          onChange={handleStockCheck}
        />{" "}
        Only show products in stock
      </p>
    </form>
  );
};

const ProductTable = ({ products, inStockOnly, filterText }) = > {
  const rows = [];
  let lastCategory = null;

  products.forEach((product) = > {
    if (product.name.indexOf(filterText) === -1) {
      return;
    }
    if(inStockOnly && ! product.stocked) {return;
    }
    if(product.category ! == lastCategory) { rows.push(<ProductCategoryRow
          category={product.category}
          key={product.category}
        />
      );
      rows.push(<ProductRow product={product} key={product.name} />);
    }
    lastCategory = product.category;
  });

  return (
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>{rows}</tbody>
    </table>
  );
};
Copy the code

conclusion

Did not React philosophy of profound truth, on the contrary it more advocate we write the code more concise and clear, more modular, it is especially important when writing a large project, before you write the code involved the general structure and data structure design, reduces the production of bugs, reduce the time of the refactoring, reducing maintenance cost.