繁体   English   中英

停止重新渲染父组件。 仅重新渲染子组件

[英]Stop Re-Rendering of Parent Components. Only Re-Render Child Component

我在 Formik 字段中有一个 React-Select 字段,当您从下拉选项中选择一个项目时,所有父组件都会重新呈现。 这是容器中可用的最深的子组件。

它重新渲染了 4 个父级。 这有点问题。 我想将组件的重新渲染限制为仅其自身。

The above happens because each Child Process passes
props to the Container, which is the master form.
And onSubmit it takes all the info(props) and makes the API Call.

我试过用shouldComponentUpdate但没有运气。 我试图用SetState来做到这一点,但这虽然掉入水中,因为我无法让它工作(有很多错误)。

--TLDR--问题:使组件仅保留其自身的渲染。 其中使用的外部组件FormikReact-Select

这是代码:

            <div className="w-50">
              <Field
                name={`${keyField}.${index}.permissions`}
                render={({ field: { value, name }, form: { setFieldValue, setFieldTouched } }) => (
                  <div>
                    <label htmlFor="namespace-permissions" className="font-weight-medium">
                      Permissions in Namespace <Asterisk />
                    </label>
                    <Select
                      isMulti
                      closeMenuOnSelect={false}
                      id="namespace-permissions"
                      defaultValue={convertNamespaceToDefaultValue(
                        dependencies.namespacePermissions,
                        value
                      )}
                      options={convertNamespaceToSelect(dependencies.namespacePermissions)}
                      onChangeCallback={values => {
                        setFieldValue(name, convertSelectToNamespacesData(values));
                        setFieldTouched(name, true);
                      }}
                    />
                    <ErrorMessage name={name} component={FormErrorMessage} />
                  </div>
                )}
              />
            </div>

dependacies prop 是使树上的旅程,到主窗体 Props,并重新渲染整个组件树的原因。 这也与我昨天遇到的另一个问题有关,关于 react-select 的closeMenuOnSelect={false}无法正常工作。

^这就是发生这种情况的原因。 谢谢..

我不知道您如何使用您正在使用的库来做到这一点。 但是当我不希望我的组件不必要地渲染时,我使用React.memo它会浅比较props对象并决定是否需要更新。

来自 React DOCS

无反应备忘录

 function App() { return( <Parent1/> ); } function Parent1(props) { console.log('Rendering Parent1...'); const [parentState,setParentState] = React.useState(true); return( <Parent2 setParentState={setParentState} /> ); } function Parent2(props) { console.log('Rendering Parent2...'); return( <Child setParentState={props.setParentState} /> ); } function Child(props) { console.log('Rendering Child...'); return( <button onClick={()=>props.setParentState((prevState)=>!prevState)}>Update ParentState</button> ); } ReactDOM.render(<App/>, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id="root"/>

带有反应备忘录

 function App() { return( <Parent1/> ); } function Parent1(props) { console.log('Rendering Parent1...'); const [parentState,setParentState] = React.useState(true); return( <Parent2 setParentState={setParentState} /> ); } const Parent2 = React.memo(function Parent2(props) { console.log('Rendering Parent2...'); return( <Child setParentState={props.setParentState} /> ); } ); const Child = React.memo(function Child(props) { console.log('Rendering Child...'); return( <button onClick={()=>props.setParentState((prevState)=>!prevState)}>Update ParentState</button> ); } ); ReactDOM.render(<App/>, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id="root"/>

我会检查 Formik 的 onSubmit 是否被调用,以及是否触发了树重新渲染。 如果您有一个type=button可能会触发表单提交。

在 v2 之前的 Formik 也有一个错误,如果通过rendercomponent道具给定渲染功能,则 Field 将在每次更新时挂载和卸载它的所有子项。 而是将渲染函数作为 Fields 子项传递。

暂无
暂无

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

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