Javascript 何时从将嵌套组件变量存储在this.props vs.this.state中切换

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中,直到我找到最低的子组件

我又回到React,试图复制一篇instagram帖子。不变的变量,如海报的名称、位置等,我认为我对如何处理有着坚实的理解。我将它们保存在
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表单,以确保在继续之前有一个坚实的理解。无论是否需要实时更新,正如您所说,当您获取挂载上的帖子时,它们最终将处于状态,因此最好的方法是将单个帖子作为道具传递给子组件,并回调到父级以更新帖子。正如我所说,任何有可能