简体   繁体   English

如何更新反应 state

[英]How to update react state

I have a list of results from my search output.我有一个搜索结果列表 output。 Each result has an onclick function.每个结果都有一个onclick function。 I want to display each of the results that the user clicks, and for now I can add each result that the user clicks to an array using this function:我想显示用户单击的每个结果,现在我可以使用此 function 将用户单击的每个结果添加到数组中:

let selectedData = []

function addFunc(resultdata){
    console.log(resultdata)
    selectedData = [...selectedData, resultdata]
    console.log(selectedData)
  };

I'm new to React, but I know this isn't the right way and I might have to use states or react hooks.我是 React 的新手,但我知道这不是正确的方法,我可能不得不使用状态或反应钩子。 The problem is that because I am using Elasticsearch to output the results, my results are in a function, not the main class.问题是因为我使用的是Elasticsearch到output的结果,所以我的结果是在一个function中,而不是主要的output。 Like this:像这样:

class Search extends Component {
    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={RenderItem}
                     />
          </ReactiveBase>
          <div>
          </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;
  }


  function RenderItem(res, triggerClickAnalytics) {
    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>
      );
  }

Basically, my ReactiveList component is what shows the results.基本上,我的ReactiveList组件显示了结果。 This calls the RenderItem function, which is what displays the data on the screen.这调用了RenderItem function,这是在屏幕上显示数据的内容。 In my function, I have a list called resultdata , which contains all the data I need when each result is clicked on.在我的 function 中,我有一个名为resultdata的列表,其中包含单击每个结果时我需要的所有数据。 This works, but I need it to display on the screen.这有效,但我需要它显示在屏幕上。

I can't use state, because I have a function.我不能使用 state,因为我有一个 function。 And I can't use hooks because it isn't the main function.而且我不能使用钩子,因为它不是主要的 function。 Am I doing something wrong?难道我做错了什么? Is there any other alternative to this?还有其他选择吗?

Even if you can't provide a complete answer, I would appreciate any tips on which direction I should look towards.即使您无法提供完整的答案,我也将不胜感激有关我应该朝着哪个方向发展的任何提示。

state is async so it wont update like this: state 是异步的,因此不会像这样更新:

function addFunc(resultdata){
    console.log(resultdata)
    selectedData = [...selectedData, resultdata]
    console.log(selectedData)
  };

and you are using a class so you can't useHooks but setState takes a callback as second argument并且您使用的是useHooks所以您不能使用 Hooks 但setState将回调作为第二个参数

function addFunc(resultdata){
    console.log(resultdata)
    this.setState({selectedData: [...selectedData, resultdata]}, () => console.log(selectedData))
  };

so if you continue using a Class approach this will allow you to use setState and utilize the callback in it因此,如果您继续使用Class方法,这将允许您使用setState并利用其中的回调

there is a callback available too in hooks but it doesn't work quite the same钩子中也有一个可用的回调,但它的工作原理并不完全相同

Place addFunc within the parent component and make your RenderItem function a React Functional component by exporting it.将 addFunc 放在父组件中,并通过导出它使您的 RenderItem function 成为 React 功能组件。 Then provide the addFunc as a function prop from parent component to RenderItem component.然后将 addFunc 作为 function 属性从父组件提供给 RenderItem 组件。 That way you can call the function within onClick event.这样您就可以在 onClick 事件中调用 function。 Any of the parent states can be updated from the addFunc.任何父状态都可以从 addFunc 更新。 You can supply necessary arguments to the function call as well.您也可以向 function 调用提供必要的 arguments。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM