根组件
<Provider store={Store}>
<AppLayoutContainer>
{this.props.template}
</AppLayoutContainer>
</Provider>
AppLayoutContainer
....some code
return(
<div className={`AppLayoutContainer`}>
<Modal isOpen={isModalShown} .... />
<div>{children}</div>
</div>
)
....some code
function mapStateToProps(state) {
const { app } = state;
return {
isModalShown: app.isModalShown
}
}
export default connect(mapStateToProps)(AppLayoutContainer);
每当Applayoutcontainer从Redux获得isModalShown
时,我的整个应用都会重新渲染,而且非常糟糕。我只需要重新渲染模态组件而不要触摸我的children
。我认为使用ShouldComponentUpdate
方法可行,但我真的不明白该怎么做。
有什么想法吗?我知道有人在他的项目中做过这件事并可以为此提出一些最佳实践建议。感谢
阅读所有答案,是的,将Modal与Store连接是一个很好的解决方案, 但是,如果
1)我希望Modal组件是纯粹的(可重用的)或组件吗?
2)我需要在AppLayoutContainer中使用isModalShown
吗?
return(
<div className={`AppLayoutContainer`}>
<Modal isOpen={isModalShown} .... />
<div>{children}</div>
</div>
)
感谢您的回答,但我该怎么办
当我显示Modal
组件时,我需要模糊我的所有内容的主要问题,因为我知道blur()
只能应用于要工作的内容(而不是覆盖我的内容的绝对位置div) )并按照这样做
return(
<div className={`AppLayoutContainer`}>
<Modal isOpen={isModalShown} .... />
<div className={isModalShown ? 'blured' : null }>{children}</div>
</div>
)
但每当我出现Modal
时,我的整个应用都会重新呈现,我需要冻结它。为child
构建容器并且在shouldcomponentupdate
执行import tensorflow as tf
import numpy as np
import tempfile
tmp_filename = 'tf.tmp'
sequences = [[1, 2, 3], [1, 2], [3, 2, 1]]
label_sequences = [[0, 1, 0], [1, 0], [1, 1, 1]]
def make_example(input_sequence, output_sequence):
"""
Makes a single example from Python lists that follows the
format of tf.train.SequenceExample.
"""
example_sequence = tf.train.SequenceExample()
# 3D length
sequence_length = len(input_sequence)
example_sequence.context.feature["length"].int64_list.value.append(sequence_length)
input_characters = example_sequence.feature_lists.feature_list["input_characters"]
output_characters = example_sequence.feature_lists.feature_list["output_characters"]
for input_character, output_character in zip(input_sequence,
output_sequence):
if input_sequence is not None:
input_characters.feature.add().int64_list.value.append(input_character)
if output_characters is not None:
output_characters.feature.add().int64_list.value.append(output_character)
return example_sequence
# Write all examples into a TFRecords file
def save_tf(filename):
with open(filename, 'w') as fp:
writer = tf.python_io.TFRecordWriter(fp.name)
for sequence, label_sequence in zip(sequences, label_sequences):
ex = make_example(sequence, label_sequence)
writer.write(ex.SerializeToString())
writer.close()
def read_and_decode_single_example(filename):
filename_queue = tf.train.string_input_producer([filename],
num_epochs=None)
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
context_features = {
"length": tf.FixedLenFeature([], dtype=tf.int64)
}
sequence_features = {
"input_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64),
"output_characters": tf.FixedLenSequenceFeature([], dtype=tf.int64)
}
return serialized_example, context_features, sequence_features
save_tf(tmp_filename)
ex,context_features,sequence_features = read_and_decode_single_example(tmp_filename)
context_parsed, sequence_parsed = tf.parse_single_sequence_example(
serialized=ex,
context_features=context_features,
sequence_features=sequence_features
)
sequence = tf.contrib.learn.run_n(sequence_parsed, n=1, feed_dict=None)
#check if the saved data matches the input data
print(sequences[0] in sequence[0]['input_characters'])
的解决方案并不好,React如何比较整个组件?它只比较道具中不可变的字段。
任何解决方案?
答案 0 :(得分:4)
您应该做的不是通过isModal
的{{1}}函数中的AppLayoutContainer
,而是通过mapStateToProps
connect
本身。{/ p >
Modal
更改的任何结果都会导致mapStateToProps
ed组件重新呈现。在您的情况下,connect
mapStateToProps
转到connect
会返回AppLayoutContainer
的值,这会导致isModalShown
重新呈现。
如果您只想重新呈现AppLayoutContainer
本身,那么只需
Modal
在您的export default connect(state => ({isOpen: state.app.isModalShown}))(Modal)
文件中,如果您更喜欢,也可以在单独的文件中。
同时从Modal
移除isModalShown
道具,因为您不需要和,因为将其留在那里意味着AppLayoutContainer
每次都会重新渲染AppLayoutContainer
更改(这是您要修复的内容)。
更新:
问题1:
您可以拥有纯isModalShown
Modal
然后,您可以为特定用途制作特定的模态:
export default function Modal(props) {
return <span>Open={props.isOpen}</span>;
}
对于各种单独的模态,您可以多次执行此操作。事实上,这就是使用纯组件的好主意。
问题2:
如果您想在import Modal from './modal';
import { connect } from 'react-redux';
export default const AppLayoutModal = connect(state => ({isOpen: state.app.isModalShown}))(Modal);
中使用isModalShown
,那么您有一些选择:
AppLayoutContainer
直接使用isModalShown
,这样大connect
就不会改变。子组件可以独立于其父组件进行更新。更新2
要模糊整个应用,只需在应用中添加一个类。子组件不会重新渲染。 Redux会阻止孩子渲染,因为它会注意到孩子们没有使用AppLayoutContainer
。生成的React元素与前一个渲染完全相同的对象(引用)。 React看到它是相同的元素,并且知道不更新整个树。这是有效的,因为React元素是不可变的。您的整个应用程序都不会重新呈现。实际上,React将仅在类属性中添加或删除该类。
如果您的孩子不使用Redux来阻止渲染器在树上行走,那么您可以将子项包装在Redux连接组件中。或者,您可以使用isModalShown
来阻止孩子的渲染。
Bare React要求您从根目录向下发送数据。 Redux要求您将数据注入树中所需的位置。后者的好处是没有其他任何东西需要重新渲染。如果没有Redux,除了组件使用shouldComponentUpdate
停止传播时,每个更改都会重新呈现整个树 。但是,这不仅会为当前组件停止渲染,也会为所有子组件停止渲染。 Redux消除了这种情况,因为子组件可以在没有父母的合作或知识的情况下更新其道具。
简而言之:到处都使用Redux来提高速度。
答案 1 :(得分:1)
这里有不同的策略。
shouldComponentUpdate
(在这种情况下非常杂乱且不优雅); AppLayoutContainer
; isModalShown
存储在Modal
状态,而不是全局状态。如果可能,最后的解决方案往往是更合适的恕我直言。您将UI状态保留在相关组件中,因为您不需要经常在其他组件中了解这一点。
class Modal extends Component {
state = {
isModalShown: false,
};
render() {
// ...
}
}
如果您需要在其他地方了解isModalShown
,则应该连接Modal
组件而不是AppLayoutContainer
。
export default connect((state) => ({
isModalShown: state.app.isModalShown,
}))(Modal)
答案 2 :(得分:0)
我认为DDS和Anthony Dugois有权利,但如果这些不是您正在寻找的答案,您可以随时将children
传递到新组件中,并使用{{1}那里。