在地图函数内部调用useState挂钩导致无限循环

时间:2020-02-05 15:34:49

标签: reactjs react-hooks

我当前正在构建一个动态表单引擎,并且希望在呈现“答案摘要”组件时显示redux存储中的结果。我认为最好的方法是拥有一个“完成”状态,并在加载answerSummary组件后将其设置为true,但是在map函数中执行此操作将不起作用,并引发无限循环反应错误。 / p>

代码在这里:

function App() {
  let [complete, setComplete] = useState(false);
  return (
    <div>
      <h1>Form App Prototype</h1>
      <Router>
        <Switch>
          {Object.values(Database.steps).map(step => {
            step.name === 'answerSummary' ? setComplete(true) : setComplete(false);
            return (

              <Route exact path={`/${step.name}`} render={() =>
                <Step step={step} />

              }
              />
            )
          })}
        </Switch>
      </Router>
        <br></br>
        <div style={{display: complete? 'block' : 'none'}}><StoreVisual/></div>

    </div>
  );
}

export default App;

编辑:我知道您无法在渲染器中设置setState-我已经以此方式编写它,以尝试传达我想要做的事情

4 个答案:

答案 0 :(得分:1)

我对您的问题的理解是,您在尝试安装答案摘要组件后尝试显示结果。 您可以使用useEffect挂钩来实现此目的,该挂钩在组件安装时运行。 https://reactjs.org/docs/hooks-effect.html

答案 1 :(得分:0)

您不能在render内设置会导致无限循环的状态。[每当状态更改时,组件都会重新渲染(调用render函数)]

render()=> setState()=> render()=> setState().......无限

WorkAround:

a=09800214851900C3

jsonfile.json | jq '.${a}.label'

答案 2 :(得分:0)

如果只想在<StoreVisual/>处于最后一步时呈现它们,则可能更容易为人所在的一步的索引设置状态钩子。

 const [index, setIndex] = useState(0);

每当有人进行一步操作时,都会将此值递增。

您必须将setIndex或任何您称为setter的东西传递到Step组件中。

然后,您可以像这样用条件渲染<StoreVisual/> ...

<div>
      <h1>Claimer Form App Prototype</h1>
      <Router>
        <Switch>
          {Object.values(Database.steps).map(step => 
              <Route exact 
                     path={`/${step.name}`} 
                     render={() => <Step step={step} /> }/> )}
        </Switch>
      </Router>
        <br></br>
        {Database.steps[index] === 'answerSummary' && <StoreVisual/>}
    </div>

这种方法还为您提供了一种简单的方法,使人们可以从表单的中间开始。假设您想让人们将来保存半成品表格,只需更改/更新索引挂钩的默认值即可。

答案 3 :(得分:0)

不要在返回时内联运行该代码,而是在函数逻辑中构建数组:

function App() {
  let [complete, setComplete] = useState(false);
  // build an array of Route components before rendering
  // you should also add a unique key prop to each Route element
  const routes = Object.values(Database.steps).map(step => {
    step.name === 'answerSummary' ? setComplete(true) : setComplete(false);
    return <Route exact path={`/${step.name}`} render={() => <Step step={step} />} />
  })
  return (
    <div>
      <h1>Claimer Form App Prototype</h1>
      <Router>
        <Switch>
          // render the array 
          {[routes]}
        </Switch>
      </Router>
      <br></br>
      <div style={{display: complete? 'block' : 'none'}}><StoreVisual/></div>
    </div>
  );
}

export default App;

我认为您无需根据此逻辑调用setComplete(false),因此您可能应该用if语句替换三元组:

if (step.name === 'answerSummary') {
  setComplete(true)
}

并避免进行不必要的函数调用