javascript - 何时从在 this.props 与 this.state 中存储嵌套组件变量切换

标签 javascript reactjs react-native

我正在重新使用 React 并尝试复制 Instagram 帖子。不会改变的变量,例如海报的名称、位置等,我想我对如何处理有充分的了解。我将它们保留在 this.props 链中,因为从用户 Angular 来看它们是不可变的。但当涉及到“ react ”之类的东西时,我不确定何时开始将它们存储在 this.statethis.props 中,因为多个 嵌套级别。

我是否应该将所有嵌套组件的与 react 数组/对象相关的数据保存在 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>
    );
  }
}

Post.js

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>
        );
    }
}

ReactionList.js

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>
            )
        }
    }
}

Reaction.js

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_DATA完全在状态内部,因为这将大大简化保存帖子信息的父组件和子帖子组件的行为。

例如,如果您不只是让用户编辑 react ,而是希望帖子所有者能够编辑 POST_DATA 的正文或位置,该怎么办? ?或者,如果您希望可以访问 react 计数,即一个单独的模式(当您单击帖子时)怎么办?

使该设计面向 future 的一种方法是,在保持简单的同时发送整个 POST_DATA给您<Post>组件,如果您不想使用 Redux 等库来处理状态,请向上提升回调以进行编辑:

Here's a simplified Codesandbox I did of this implementation .

<InstaPost
  post={this.state.post}               <-- this.state.post holds POST_DATA 
  handleReactionClick={this.handleReactionClick}
  handleBodyEdit={this.handleBodyEdit} <-- if we decide to implement this later on
/>

为什么在应用/组件状态下将网络数据保存为不可变对象(immutable对象)?

将帖子数据作为不可变对象(immutable对象)(在我使用 immer.js 的示例中)保存在状态中的好处是,例如,如果 Instagram 或 Facebook 的工作方式是这样,当您单击“爱” react ,针对您的 react 发送 API 请求,并返回实时更新的 react 值:

例如,如果我按下“Like (2)”,然后又有 10 个人像之前一样按下,API 不会返回“3”(2+1),而是返回“13”(2 + 1 + 10)。使用您当前的设计来处理这个问题比我建议的设计需要更多的工作。

就我个人而言,我更喜欢使用 Redux 之类的库来获取应用程序状态,但对于小型原型(prototype)来说则没有必要。但是,如果涉及网络获取/更新,我建议始终使用不可变对象(immutable对象),无论项目大小如何。

希望这有帮助!

关于javascript - 何时从在 this.props 与 this.state 中存储嵌套组件变量切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58045336/

相关文章:

javascript - 错误: Unable to resolve module `react-redux` from `C:\Users\wanuuu27\AwesomeProject\App.js` : Module `react-redux` does not exist

responsive-design - 如何 react 原生文本和图像响应?小型设备中较小的文本和图像,大型设备中较大的文本和图像

javascript - 仅在第一次访问 C# 网页时显示消息

javascript - 如何在app.run中使用异步代码?

javascript - 尝试创建 Backbone.js View 子类时出错

javascript - 试图映射到React

javascript - React Redux 调度有效负载到达带有数据的情况,但不保存它

javascript - 如何在 react 中解析xml文件?

javascript - React Js组件动态改变h1标签

javascript - 为什么会跳过将值插入数组?