Javascript 何时从将嵌套组件变量存储在this.props vs.this.state中切换
我又回到React,试图复制一篇instagram帖子。不变的变量,如海报的名称、位置等,我认为我对如何处理有着坚实的理解。我将它们保存在Javascript 何时从将嵌套组件变量存储在this.props vs.this.state中切换,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我又回到React,试图复制一篇instagram帖子。不变的变量,如海报的名称、位置等,我认为我对如何处理有着坚实的理解。我将它们保存在this.props的链条中,因为它们从用户角度来看是不可变的。但是当涉及到类似“反应”的东西时,我不确定什么时候开始将它们存储在this.state与this.props中,因为嵌套的层次很多 我是否应该将与我的反应数组/对象相关的数据一直保存在所有嵌套组件的this.state(如下所述)中?或者将它们保存在this.props中,直到我找到最低的子组件
this.props
的链条中,因为它们从用户角度来看是不可变的。但是当涉及到类似“反应”的东西时,我不确定什么时候开始将它们存储在this.state
与this.props
中,因为嵌套的层次很多
我是否应该将与我的反应数组/对象相关的数据一直保存在所有嵌套组件的this.state
(如下所述)中?或者将它们保存在this.props
中,直到我找到最低的子组件
我没有任何提升状态的代码,因为我想首先确保我的架构是正确的
Home.js
const POST_DATA = [
{
name: 'Outdoors Guy',
location: 'Yosemite, CA',
id: '123',
body: 'Hello world!',
image: 'https://someurl',
reactions: [
{
reaction: 'Like',
count: 2,
selected: true
},
{
reaction: 'Love',
count: 1,
selected: false
}
]
}
];
export default class HomeScreen extends React.Component {
constructor(props){
super(props)
this.state = {
posts: POST_DATA
}
}
render(){
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<ScrollView>
<FlatList styles={styles.list}
data={this.state.posts}
renderItem={({ item }) =>
<Post
name={item.name}
location={item.location}
body={item.body}
image={item.image}
reactions={item.reactions}/>}
keyExtractor={item => item.id}/>
</ScrollView>
</View>
);
}
}
export default class Post extends Component {
constructor(props){
super(props)
state = {
// should I be doing this?
reactions: this.props.reactions
}
}
render() {
return (
<View>
<View style={styles.postHeader}>
// Example of these two variables ending their chaining here
<Text style={styles.name}>{this.props.name}</Text>
<Text style={styles.location}>{this.props.location}</Text>
</View>
<Text style={styles.body}>{this.props.body}</Text>
<Image style={styles.image} source={{uri: this.props.image}}/>
// Heres where the confusion begins
<ReactionList list={this.props.reactions}/>
</View>
);
}
}
export default class ReactionList extends Component {
constructor(props){
super(props)
state = {
reactions: this.props.reactions
}
}
render() {
if (this.state.reactions === null)
{
return (
<View>
<AddReaction/>
<FlatList styles={styles.reactionList}
data={this.state.reactions}
renderItem={({ item }) =>
<Reaction
reaction={item.reaction}
count={item.count}
selected={item.selected}/>}
keyExtractor={item => item.id}/>
</View>
)
}
else{
return (
<View>
<AddReaction/>
</View>
)
}
}
}
export default class Reaction extends Component {
constructor(props){
super(props)
state = {
// I understand these are not visible in the component
// but still want to track the data
count: this.props.count,
selected: this.props.selected
}
}
_onSelectPress () {
this.setState({
selected: !this.state.selected,
count: ++this.state.count
})
}
render() {
return (
<TouchableOpacity style={styles.reaction}
onPress={() => this._onSelectPress()}>
<Text style={styles.reactionText}>{this.props.reaction}</Text>
</TouchableOpacity>
);
}
const POST\u数据=[
{
名字:“户外男孩”,
地点:加利福尼亚州约塞米蒂,
id:'123',
身体:“你好,世界!”,
图像:'https://someurl',
反应:[
{
反应:“像”,
计数:2,
所选:真
},
{
反应:“爱”,
计数:1,
所选:false
}
]
}
];
导出默认类主屏幕扩展React.Component{
建造师(道具){
超级(道具)
此.state={
posts:POST_数据
}
}
render(){
返回(
}
keyExtractor={item=>item.id}/>
);
}
}
Post.js
const POST_DATA = [
{
name: 'Outdoors Guy',
location: 'Yosemite, CA',
id: '123',
body: 'Hello world!',
image: 'https://someurl',
reactions: [
{
reaction: 'Like',
count: 2,
selected: true
},
{
reaction: 'Love',
count: 1,
selected: false
}
]
}
];
export default class HomeScreen extends React.Component {
constructor(props){
super(props)
this.state = {
posts: POST_DATA
}
}
render(){
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<ScrollView>
<FlatList styles={styles.list}
data={this.state.posts}
renderItem={({ item }) =>
<Post
name={item.name}
location={item.location}
body={item.body}
image={item.image}
reactions={item.reactions}/>}
keyExtractor={item => item.id}/>
</ScrollView>
</View>
);
}
}
export default class Post extends Component {
constructor(props){
super(props)
state = {
// should I be doing this?
reactions: this.props.reactions
}
}
render() {
return (
<View>
<View style={styles.postHeader}>
// Example of these two variables ending their chaining here
<Text style={styles.name}>{this.props.name}</Text>
<Text style={styles.location}>{this.props.location}</Text>
</View>
<Text style={styles.body}>{this.props.body}</Text>
<Image style={styles.image} source={{uri: this.props.image}}/>
// Heres where the confusion begins
<ReactionList list={this.props.reactions}/>
</View>
);
}
}
export default class ReactionList extends Component {
constructor(props){
super(props)
state = {
reactions: this.props.reactions
}
}
render() {
if (this.state.reactions === null)
{
return (
<View>
<AddReaction/>
<FlatList styles={styles.reactionList}
data={this.state.reactions}
renderItem={({ item }) =>
<Reaction
reaction={item.reaction}
count={item.count}
selected={item.selected}/>}
keyExtractor={item => item.id}/>
</View>
)
}
else{
return (
<View>
<AddReaction/>
</View>
)
}
}
}
export default class Reaction extends Component {
constructor(props){
super(props)
state = {
// I understand these are not visible in the component
// but still want to track the data
count: this.props.count,
selected: this.props.selected
}
}
_onSelectPress () {
this.setState({
selected: !this.state.selected,
count: ++this.state.count
})
}
render() {
return (
<TouchableOpacity style={styles.reaction}
onPress={() => this._onSelectPress()}>
<Text style={styles.reactionText}>{this.props.reaction}</Text>
</TouchableOpacity>
);
}
导出默认类Post扩展组件{
建造师(道具){
超级(道具)
状态={
//我应该这样做吗?
反应:这个。道具。反应
}
}
render(){
返回(
//这两个变量在此处结束链接的示例
{this.props.name}
{this.props.location}
{this.props.body}
//这就是混乱的开始
);
}
}
ReactionList.js
const POST_DATA = [
{
name: 'Outdoors Guy',
location: 'Yosemite, CA',
id: '123',
body: 'Hello world!',
image: 'https://someurl',
reactions: [
{
reaction: 'Like',
count: 2,
selected: true
},
{
reaction: 'Love',
count: 1,
selected: false
}
]
}
];
export default class HomeScreen extends React.Component {
constructor(props){
super(props)
this.state = {
posts: POST_DATA
}
}
render(){
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<ScrollView>
<FlatList styles={styles.list}
data={this.state.posts}
renderItem={({ item }) =>
<Post
name={item.name}
location={item.location}
body={item.body}
image={item.image}
reactions={item.reactions}/>}
keyExtractor={item => item.id}/>
</ScrollView>
</View>
);
}
}
export default class Post extends Component {
constructor(props){
super(props)
state = {
// should I be doing this?
reactions: this.props.reactions
}
}
render() {
return (
<View>
<View style={styles.postHeader}>
// Example of these two variables ending their chaining here
<Text style={styles.name}>{this.props.name}</Text>
<Text style={styles.location}>{this.props.location}</Text>
</View>
<Text style={styles.body}>{this.props.body}</Text>
<Image style={styles.image} source={{uri: this.props.image}}/>
// Heres where the confusion begins
<ReactionList list={this.props.reactions}/>
</View>
);
}
}
export default class ReactionList extends Component {
constructor(props){
super(props)
state = {
reactions: this.props.reactions
}
}
render() {
if (this.state.reactions === null)
{
return (
<View>
<AddReaction/>
<FlatList styles={styles.reactionList}
data={this.state.reactions}
renderItem={({ item }) =>
<Reaction
reaction={item.reaction}
count={item.count}
selected={item.selected}/>}
keyExtractor={item => item.id}/>
</View>
)
}
else{
return (
<View>
<AddReaction/>
</View>
)
}
}
}
export default class Reaction extends Component {
constructor(props){
super(props)
state = {
// I understand these are not visible in the component
// but still want to track the data
count: this.props.count,
selected: this.props.selected
}
}
_onSelectPress () {
this.setState({
selected: !this.state.selected,
count: ++this.state.count
})
}
render() {
return (
<TouchableOpacity style={styles.reaction}
onPress={() => this._onSelectPress()}>
<Text style={styles.reactionText}>{this.props.reaction}</Text>
</TouchableOpacity>
);
}
导出默认类ReactionList扩展组件{
建造师(道具){
超级(道具)
状态={
反应:这个。道具。反应
}
}
render(){
if(this.state.reactions===null)
{
返回(
}
keyExtractor={item=>item.id}/>
)
}
否则{
返回(
)
}
}
}
Reaction.js
const POST_DATA = [
{
name: 'Outdoors Guy',
location: 'Yosemite, CA',
id: '123',
body: 'Hello world!',
image: 'https://someurl',
reactions: [
{
reaction: 'Like',
count: 2,
selected: true
},
{
reaction: 'Love',
count: 1,
selected: false
}
]
}
];
export default class HomeScreen extends React.Component {
constructor(props){
super(props)
this.state = {
posts: POST_DATA
}
}
render(){
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<ScrollView>
<FlatList styles={styles.list}
data={this.state.posts}
renderItem={({ item }) =>
<Post
name={item.name}
location={item.location}
body={item.body}
image={item.image}
reactions={item.reactions}/>}
keyExtractor={item => item.id}/>
</ScrollView>
</View>
);
}
}
export default class Post extends Component {
constructor(props){
super(props)
state = {
// should I be doing this?
reactions: this.props.reactions
}
}
render() {
return (
<View>
<View style={styles.postHeader}>
// Example of these two variables ending their chaining here
<Text style={styles.name}>{this.props.name}</Text>
<Text style={styles.location}>{this.props.location}</Text>
</View>
<Text style={styles.body}>{this.props.body}</Text>
<Image style={styles.image} source={{uri: this.props.image}}/>
// Heres where the confusion begins
<ReactionList list={this.props.reactions}/>
</View>
);
}
}
export default class ReactionList extends Component {
constructor(props){
super(props)
state = {
reactions: this.props.reactions
}
}
render() {
if (this.state.reactions === null)
{
return (
<View>
<AddReaction/>
<FlatList styles={styles.reactionList}
data={this.state.reactions}
renderItem={({ item }) =>
<Reaction
reaction={item.reaction}
count={item.count}
selected={item.selected}/>}
keyExtractor={item => item.id}/>
</View>
)
}
else{
return (
<View>
<AddReaction/>
</View>
)
}
}
}
export default class Reaction extends Component {
constructor(props){
super(props)
state = {
// I understand these are not visible in the component
// but still want to track the data
count: this.props.count,
selected: this.props.selected
}
}
_onSelectPress () {
this.setState({
selected: !this.state.selected,
count: ++this.state.count
})
}
render() {
return (
<TouchableOpacity style={styles.reaction}
onPress={() => this._onSelectPress()}>
<Text style={styles.reactionText}>{this.props.reaction}</Text>
</TouchableOpacity>
);
}
导出默认类组件{
建造师(道具){
超级(道具)
状态={
//我知道这些在组件中不可见
//但仍然希望跟踪数据
计数:这个。道具。计数,
已选择:this.props.selected
}
}
_onSelectPress(){
这个.setState({
已选定:!this.state.selected,
计数:++this.state.count
})
}
render(){
返回(
这是。_onSelectPress()}>
{this.props.reaction}
);
}
如果对您有意义,您可以将POST_数据完全存储在状态中,因为这将大大简化保存POST信息的父组件和子POST组件的行为
例如,如果您不只是让用户编辑反应,而是希望帖子所有者能够编辑post\u数据的主体或位置,该怎么办?或者,如果你想让反应成为可接受的,比如说,一个单独的模式(当你点击帖子时)
在保持设计简单的同时,一种未来验证此设计的方法是将整个POST_数据
发送到
组件,如果您不想使用诸如Redux之类的库来处理状态,则可提起回调进行编辑:
如果对您有意义,您可以将POST_数据完全存储在状态中,因为这将大大简化保存POST信息的父组件和子POST组件的行为
例如,如果您不只是让用户编辑反应,而是希望帖子所有者能够编辑post\u数据的主体或位置,该怎么办?或者,如果你想让反应成为可接受的,比如说,一个单独的模式(当你点击帖子时)
在保持设计简单的同时,一种未来验证此设计的方法是将整个POST_数据
发送到
组件,如果您不想使用诸如Redux之类的库来处理状态,则可提起回调进行编辑:
1)计划对componentDidMount
中的帖子列表执行GET req,并将帖子数组设置为状态。(POST_数据将是传递给FlatList数据的帖子数组)2)Instagram的UI不会实时更新,当您喜欢一篇帖子时,数据库会随您的操作更新,但您必须手动刷新才能看到其他喜欢的帖子。我认为这使他们能够简化他们的重新招标代码。3) 我查看了Redux,但想做纯React表单,以确保在继续之前有一个坚实的理解。无论是否需要实时更新,正如您所说,当您获取挂载上的帖子时,它们最终将处于状态,因此最好的方法是将单个帖子作为道具传递给子组件,并回调到父级以更新帖子。正如我所说,任何有可能