【问题标题】:How do I keep focus on my react input field once the onchange fires?一旦 onchange 触发,我如何将注意力集中在我的反应输入字段上?
【发布时间】:2022-08-13 23:24:15
【问题描述】:

较新的反应。我在具有输入文本框的 ReactTable 中有此列。我知道更改状态是重新渲染表单,只是不确定如何防止这种情况。感谢任何指导!

      <ReactTable
          key={googlecampaigndata?.length}
          data={googlecampaigndata}
          loading={googlecampaignloading}
          sortable={false}
          filterable={false}
                        
          columns={[
            {
              Header: \"Account Name\",
              accessor: \"customer_name\"
            },
            {
              Header: \"Campaign Name\",
              accessor: \"campaign_name\"
            },
            {
              Header: \"Campaign Type\",
              accessor: \"campaign_type\"
            },
            {
              Header: \"Status\",
              accessor: \"status\"
            },
            {
              Header: \"Monthly Budget\",
              accessor: \"monthly_budget\"
            },
            {
              Header: \"Update Monthly Budget\",
              accessor: \"update_monthly_budget\",                
              Cell: ({ original }) => {
                return (
                  <form
                    onSubmit={e => {
                      e.preventDefault();
                      if(submissionData !== {} && submitGoogleCampaignMonthlyBudgetForm()){
                        refetch();
                        }  
                      }
                    }
                  >
                  <input
                    id={`monthly_budget${original.id}`}
                    type=\"text\"
                    maxLength=\"12\" 
                    size=\"8\"
                    style={{ float: \"left\" }}
                    onChange = {updateFieldHandler(\"monthly_budget\", original.id)}
                    inputprops={{
                      type: \"string\",
                      required: true,
                      value: original[\'monthly_budget\'] ? original[\'monthly_budget\'] : \"\"
                    }}
                  /><Button 
                      color=\"primary\" 
                      type=\"submit\"
                      style={{ float: \"right\" }}
                      >
                    Submit
                  </Button>
              </form>
                );
              },
            },
            {
              Header: \"Cycle Start Date\",
              accessor: \"date\"
            }
          ]}
          defaultPageSize={Math.min(pageSize, googlecampaigndata?.length || 2)}
          showPaginationTop
          showPaginationBottom={false}
          onPageSizeChange={ps => setPageSize(ps)}
          className=\"-striped -highlight\"
        />

#编辑 我尝试从 MyAccounts 外部返回我的输入字段,但在输入时我仍然无法专注于输入。下面是我更新的更多代码。

            import React, { useState, useContext, useEffect } from \"react\";
            import { useQuery, useMutation } from \"@apollo/react-hooks\";
            import { intersection, omit } from \"lodash\";

            // @material-ui/core components
            import { makeStyles } from \"@material-ui/core/styles\";
            // @material-ui/icons
            import Assignment from \"@material-ui/icons/Assignment\";

            // core components
            import GridContainer from \"components/Grid/GridContainer\";
            import GridItem from \"components/Grid/GridItem\";
            import Card from \"components/Card/Card\";
            import CardBody from \"components/Card/CardBody\";
            import CardIcon from \"components/Card/CardIcon\";
            import CardHeader from \"components/Card/CardHeader\";
            import ReactTable from \"components/CustomReactTable\";
            import Button from \"components/CustomButtons/Button\";
            import { cardTitle } from \"assets/jss/material-dashboard-pro-react\";
            import { SUBMIT_GOOGLE_CAMPAIGN_MONTHLY_BUDGET_FORM } from \"queries/formSubmission\";
            import { LIST_BUDGETS } from \"queries/budget\";
            import { GET_GOOGLE_CAMPAIGNS } from \"queries/budget\";
            import { Context } from \"redux/store\";

            const styles = {
              cardIconTitle: {
                ...cardTitle,
                marginTop: \"15px\",
                marginBottom: \"0px\"
              }
            };

            const useStyles = makeStyles(styles);


            const GoogleCampaignMonthlyBudgetInput = ({ original, setSubmissionData, submissionData, state, onChange }) => {
              return (
                <input
                  id={`monthly_budget${original.id}`}
                  type=\"text\"
                  maxLength=\"12\" 
                  size=\"8\"
                  style={{ float: \"left\" }}
                  key={original.id}
                  onChange={ onChange }
                  value={submissionData.id === original.id ? submissionData.monthly_budget : original.monthly_budget ? (original.monthly_budget / (1 - (state.customers?.selected?.margin / 100.0))) / 1000000 : \"\"}
                  inputprops={{
                    type: \"string\",
                    required: true,
                  }}
                />
              );
            }

            const MyAccounts = () => {
              const [state] = useContext(Context);
              const [pageSize, setPageSize] = useState(20);
              const customer_id = state.customers?.selected?.id;
              const [submissionData, setSubmissionData] = useState({});
              let { loading, data } = useQuery(LIST_BUDGETS);
              let { loading: googlecampaignloading, data: googlecampaigndata, refetch } = useQuery(GET_GOOGLE_CAMPAIGNS);
              googlecampaigndata = googlecampaigndata?.getGoogleCampaigns || [];
              data = data?.listBudgets || [];

              data = data.map((row, index) => {
                let customer_name = \"\";
                let product_line = \"\";
                if (
                  index % pageSize === 0 ||
                  row.customer_name !== data[index - 1].customer_name
                ) {
                  customer_name = row.customer_name;
                }
                if (
                  index % pageSize === 0 ||
                  row.product_line !== data[index - 1].product_line
                ) {
                  product_line = row.product_line;
                }
                return {
                  ...row,
                  customer_name,
                  product_line
                };
              });
              const [submitGoogleCampaignMonthlyBudgetForm, { loading: submitting }] = useMutation(
                SUBMIT_GOOGLE_CAMPAIGN_MONTHLY_BUDGET_FORM,
                {
                  variables: {
                    customerId: customer_id,
                    data: submissionData
                  },
                  onCompleted: () => {
                  return true;
                  }
                }
              );

              const classes = useStyles();
              return (
                <GridContainer>
                   <GridItem xs={12}>
                    <Card>
                      <CardHeader color=\"trackedKeywords\" icon>
                        <CardIcon>
                          <Assignment />
                        </CardIcon>
                        <h4 className={classes.cardIconTitle}>Google Campaigns</h4>
                      </CardHeader>
                      <CardBody>
                        <ReactTable
                          key={googlecampaigndata?.length}
                          data={googlecampaigndata}
                          loading={googlecampaignloading}
                          sortable={false}
                          filterable={false}
                                        
                          columns={[
                            {
                              Header: \"Monthly Budget\",
                              accessor: \"monthly_budget\",
                              Cell: ({ original }) => {
                                return (
                                  <div>{original.monthly_budget ? (original.monthly_budget / (1 - (state.customers?.selected?.margin / 100.0))) / 1000000 : \"\"}</div>
                                  );
                              },
                            },
                            {
                              Header: \"Update Monthly Budget\",
                              accessor: \"update_monthly_budget\",                
                              Cell: ({ original }) => {                    
                                return (
                                  <form
                                    onSubmit={e => {
                                      e.preventDefault();
                                      if(submissionData !== {} && submitGoogleCampaignMonthlyBudgetForm()){
                                        refetch();
                                        }  
                                      }
                                    }
                                  >
                                  <GoogleCampaignMonthlyBudgetInput original={original} onChange={e => setSubmissionData({...submissionData, \"monthly_budget\": parseFloat(e.target.value), \"id\": original.id })} setSubmissionData={setSubmissionData} submissionData={submissionData} state={state} key={original.id}  />
                                  <Button
                                    color=\"primary\" 
                                    type=\"submit\"
                                    style={{ float: \"right\" }}
                                    >
                                  Submit
                                </Button>
                              </form>
                                );
                              },
                            },

                            {
                              Header: \"Cycle Start Date\",
                              accessor: \"date\"
                            }
                          ]}
                          defaultPageSize={Math.min(pageSize, googlecampaigndata?.length || 2)}
                          showPaginationTop
                          showPaginationBottom={false}
                          onPageSizeChange={ps => setPageSize(ps)}
                          className=\"-striped -highlight\"
                        />
                      </CardBody>
                    </Card>
                  </GridItem>
                </GridContainer>
              );
            };

            export default MyAccounts;

编辑 2:我在 inwerpsel 的帮助下得到的代码!

            {
              Header: \"Monthly Budget\",
              accessor: \"monthly_budget\",
              Cell: ({ original }) => {
                return (
                  <div>{submissionData.id === original.id ? submissionData.monthly_budget : original.monthly_budget ? (original.monthly_budget / (1 - (state.customers?.selected?.margin / 100.0))) / 1000000 : \"\"}</div>
                  );
              },
            },
            {
              Header: \"Update Monthly Budget\",
              accessor: \"update_monthly_budget\",                
              Cell: ({ original }) => {           
                const [textInput, setTextInput] = useState(null);                    

                const [submitGoogleCampaignMonthlyBudgetForm, { loading: submitting }] = useMutation(
                  SUBMIT_GOOGLE_CAMPAIGN_MONTHLY_BUDGET_FORM,
                  {
                    variables: {
                      customerId: customer_id,
                      data: submissionData
                    },
                    onCompleted: () => {
                      refetch();
                    return true;
                    }
                  }
                );

                return (
                  <form
                    key={\"form\"+original.id}
                    onSubmit={e => {
                      e.preventDefault();
                      if(Number.isNaN(textInput) || textInput === \"\" || textInput === null){
                        setSubmissionData({});
                        return;
                      }
                      submissionData[\"monthly_budget\"] = parseFloat(textInput);
                      submissionData[\"id\"] = original.id;
                      
                      if(submissionData !== {} && submitGoogleCampaignMonthlyBudgetForm()){
                        refetch();
                        setSubmissionData({});
                        }  
                      }
                    }
                  >
                  <input
                    id={`monthly_budget${original.id}`}
                    type=\"text\"
                    maxLength=\"12\" 
                    size=\"8\"
                    style={{ float: \"left\" }}
                    key={original.id}
                    onChange = {event => { setTextInput(event.target.value) }}
                    defaultValue={submissionData.id === original.id ? submissionData.monthly_budget : original.monthly_budget ? (original.monthly_budget / (1 - (state.customers?.selected?.margin / 100.0))) / 1000000 : \"\"}
                    inutprops={{
                      type: \"string\",
                      required: true,
                    }}
                  />
                  <Button
                    color=\"primary\" 
                    type=\"submit\"
                    style={{ float: \"right\" }}
                    >
                  Submit
                </Button>
              </form>
                );
              },
            },
  • 我的猜测是这条线 value={submissionData.id === original.id ? submissionData.monthly_budget : original.monthly_budget ? (original.monthly_budget / (1 - (state.customers?.selected?.margin / 100.0))) / 1000000 : \"\"} 在你的上下文 state 和你的 submissionData 状态之间创建一个循环依赖。我相信您可以使用useCallbackuseMemo 来避免这种情况。您能否在 Repl.it 上创建一个复制品,以便我们对其进行调整?

标签: reactjs input onchange react-table


【解决方案1】:

This GitHub issue 似乎表明确实会随着您的数据更改而重新安装单元格,即使这是一个很小的变化。

换句话说,当您键入时,它会用每个字符的新实例替换整行。新实例与前一个实例没有链接,即使它应该包含您键入的数据。结果它不会有焦点。

尽管我对react-table 不太熟悉,但似乎很难解决。

但是,由于您已经设置了一个带有提交处理程序的表单,我想您可以将输入存储在本地状态中,并且仅在提交时设置它。

Cell: ({ original }) => {
  const [textInput, setTextInput] = useState(null);

  return (
    <form
      onSubmit={e => {
        e.preventDefault();
        // Call the update handler here instead.
        const handler = updateFieldHandler("monthly_budget", original.id);
        handler(textInput);

        if(submissionData !== {} && submitGoogleCampaignMonthlyBudgetForm()){
          refetch();
          }  
        }
      }
    >
    <input
      // ...
      onChange = {event => { setTextInput(event.target.value) }}
      // ...
    /><Button 
        color="primary" 
        type="submit"
        style={{ float: "right" }}
        >
      Submit
    </Button>
</form>
  );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 1970-01-01
    • 2017-12-06
    相关资源
    最近更新 更多