0

I have a list of results, and each time I click on a result, it calls my addFunc function to add that particular result's details as an object in the selectedData list. Currently, this works when I console.log my selectedData list.

What I want to do is display my selectedData list, and each time a result is clicked, the object will be added to the list, and I want that to be reflected on my screen.

I believe I have to use state to do this, but I am not very sure how to. Thank you for your help.

A summary of my code is below:

let selectedData = [];

const Wrapper = cb => {
  return (res, triggerClickAnalytics) => (
    <RenderItem
      res={res}
      triggerClickAnalytics={triggerClickAnalytics}
      addFunc={cb}
    />
  );
};

class Search extends Component {
  constructor(props) {
    super(props);
    this.addFunc = this.addFunc.bind(this);
  }
  addFunc(resultdata) {
    selectedData = [...selectedData, resultdata]
    console.log(selectedData)
  }
render() {
    return (
          <ReactiveList
            componentId="results"
            dataField="_score"
            pagination={true}
            react={{
              and: ["system", "grouping", "unit", "search"]
            }}
            size={10}
            noResults="No results were found..."
            renderItem={Wrapper(this.addFunc)}
          />
        </ReactiveBase>
    );
  }
}

const RenderItem = ({ res, triggerClickAnalytics, addFunc }) => {

  let { unit, title, system, score, proposed, id } = {
    title: "maker_tag_name",
    proposed: "proposed_standard_format",
    unit: "units",
    system: "system",
    score: "_score",
    id: "_id"
  };
  const resultdata = { id, title, system, unit, score, proposed };

  return (
        <Button
          shape="circle"
          icon={<CheckOutlined />}
          style={{ marginRight: "5px" }}
          onClick={() => addFunc(resultdata)}
        />
  );
};

The whole code is in this code sandbox: https://codesandbox.io/s/little-framework-spg1w

EDIT:

I've managed to change my function to a state by editing my code as such:

  constructor(props) {
    super(props);
    this.addFunc = this.addFunc.bind(this);
    this.state = { selectedData:[] }
  }
  addFunc(resultdata) {
    var joined = this.state.selectedData.concat(resultdata);
    this.setState({ selectedData: joined })
    console.log(joined)
  }

I now need to display the results in my joined array on the screen. How do I do this?

4
  • 4
    selectedData needs to be state. It cannot be declared outside like that (unless you want impossible to debug situations to arise). Commented Jun 19, 2020 at 17:00
  • 1
    hint: constructor() { this.state = { selectedData:[] } } Commented Jun 19, 2020 at 17:02
  • That worked like a charm, thanks Adam! Could you also tell me how to make the joined array be displayed on the screen and update whenever I add an object to it? Commented Jun 19, 2020 at 17:10
  • Also, if you post your comment as an answer, I can accept it as the solution Commented Jun 19, 2020 at 17:11

1 Answer 1

1

Replace Search.js with

import React, { useState, Component } from "react";
import {
  ReactiveBase,
  DataSearch,
  MultiList,
  SelectedFilters,
  ReactiveList
} from "@appbaseio/reactivesearch";
import { Row, Button, Col } from "antd";
import { CheckOutlined } from "@ant-design/icons";

const Wrapper = cb => {
  return (res, triggerClickAnalytics) => (
    <RenderItem
      res={res}
      triggerClickAnalytics={triggerClickAnalytics}
      addFunc={cb}
    />
  );
};

class Search extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedData : []
    }
    this.addFunc = this.addFunc.bind(this);
  }
  addFunc(resultdata) {
    this.setState(prevState => ({selectedData: [...prevState.selectedData, resultdata]}))

  }
  render() {
    return (
      <div>
        <ReactiveBase
          app="datataglist"
          credentials="mRgWyoKGQ:f47be2a6-65d0-43b6-8aba-95dbd49eb882"
          url="https://scalr.api.appbase.io"
        >
          <DataSearch
            componentId="search"
            dataField={[
              "maker_tag_name",
              "maker_tag_name.autosuggest",
              "maker_tag_name.keyword"
            ]}
            fieldWeights={[6, 2, 6]}
            fuzziness={1}
            highlightField={["maker_tag_name"]}
            placeholder="Search Tag Name"
            style={{
              marginBottom: 20
            }}
            title="Maker Tag Name"
          />
          <Row gutter={16}>
            <Col span={8}>
              <MultiList
                componentId="system"
                dataField="system.keyword"
                queryFormat="or"
                size={100}
                sortBy="asc"
                style={{
                  marginBottom: 20
                }}
                title="System"
              />
            </Col>
            <Col span={8}>
              <MultiList
                componentId="grouping"
                dataField="grouping.keyword"
                size={100}
                style={{
                  marginBottom: 20
                }}
                title="Grouping"
              />
            </Col>
            <Col span={8}>
              <MultiList
                componentId="unit"
                dataField="units.keyword"
                size={100}
                style={{
                  marginBottom: 20
                }}
                title="Unit"
              />
            </Col>
          </Row>
          <SelectedFilters />
          <ReactiveList
            componentId="results"
            dataField="_score"
            pagination={true}
            react={{
              and: ["system", "grouping", "unit", "search"]
            }}
            size={10}
            noResults="No results were found..."
            renderItem={Wrapper(this.addFunc)}
          />
        </ReactiveBase>
        <div />
      </div>
    );
  }
}

function getNestedValue(obj, path) {
  const keys = path.split(".");
  const currentObject = obj;
  const nestedValue = keys.reduce((value, key) => {
    if (value) {
      return value[key];
    }
    return "";
  }, currentObject);
  if (typeof nestedValue === "object") {
    return JSON.stringify(nestedValue);
  }
  return nestedValue;
}

const RenderItem = ({ res, triggerClickAnalytics, addFunc }) => {
  // console.log(name);

  let { unit, title, system, score, proposed, id } = {
    title: "maker_tag_name",
    proposed: "proposed_standard_format",
    unit: "units",
    system: "system",
    score: "_score",
    id: "_id"
  };
  title = getNestedValue(res, title);
  system = getNestedValue(res, system);
  unit = getNestedValue(res, unit);
  score = getNestedValue(res, score);
  proposed = getNestedValue(res, proposed);
  id = getNestedValue(res, id);

  const resultdata = { id, title, system, unit, score, proposed };

  return (
    <Row
      onClick={triggerClickAnalytics}
      type="flex"
      gutter={16}
      key={res._id}
      style={{ margin: "20px auto", borderBottom: "1px solid #ededed" }}
    >
      <Col style={{ width: "360px" }}>
        <h3
          style={{ fontWeight: "600" }}
          dangerouslySetInnerHTML={{
            __html: title || "Choose a valid Title Field"
          }}
        />
      </Col>
      <div style={{ padding: "20px" }} />
      <Col>
        <p
          style={{ fontSize: "1em", width: "300px" }}
          dangerouslySetInnerHTML={{
            __html: system || "Choose a valid Description Field"
          }}
        />
      </Col>
      <div style={{ padding: "10px" }} />
      <Col>
        <p
          style={{ fontSize: "1em" }}
          dangerouslySetInnerHTML={{
            __html: unit || "-"
          }}
        />
      </Col>
      <div style={{ padding: "10px" }} />
      <Col style={{ minWidth: "120px" }}>
        <p
          style={{ fontSize: "1em", width: "300px" }}
          dangerouslySetInnerHTML={{
            __html: proposed || "Choose a valid Description Field"
          }}
        />
      </Col>
      <div style={{ padding: "10px" }} />
      <Col>
        <p
          style={{ fontSize: "1em" }}
          dangerouslySetInnerHTML={{
            __html: Math.round(score) || "Choose a valid Description Field"
          }}
        />
      </Col>
      <Col>
        <Button
          shape="circle"
          icon={<CheckOutlined />}
          style={{ marginRight: "5px" }}
          onClick={() => addFunc(resultdata)}
        />
      </Col>
    </Row>
  );
};

export default Search;
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! Do you also know how I can make the array be displayed on the screen and update whenever I add an object to it
This part is React duty. The render method called, whenever any state update.
Yes, but how do I display it on the screen in the first place? Do I use map or something?
You can display an array of JSX element in React, for example : codesandbox.io/s/fast-lake-efpxn?file=/src/App.js

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.