使用react / redux / react-native-router-flex在另一个场景中更改状态后刷新概述场景

时间:2017-06-26 21:51:01

标签: react-native redux react-redux react-native-router-flux

github提供的最简化的工作示例!!!

我有一个简单的应用程序来学习使用react native和redux构建应用程序。根据我的理解,如果您在render方法中显示redux状态的数据,然后更改此状态的值,那么该值也将更改,并且会重新呈现由于状态更改而需要重新呈现的所有组件。

我在github上提供了应用程序:https://github.com/schingeldi/checklist

非常简单。我有一个概述,如果你点击一个条目的状态,你会进入一个详细的页面。如果单击“标记xxx”,则在redux状态(根据日志)中更改状态,但在概览场景中未刷新状态。

基本上我有一个Overview.js:

class Overview extends Component {

    constructor(props) {
        super(props);
        this.state = {fetching:false};
    }

    entries() {
        // console.log("Overview");
        // console.log(this.props);
        // console.log(this.props.entries);


        return Object.keys(this.props.entries).map(key => this.props.entries[key]);
    }

    componentDidMount() {
        this.setState({fetching:true});
        this.props.actions.getEntries()
            .then( (res) => {
                this.setState({fetching: false});
            })
    }

    handleChange(entryId) {
        Actions.detail({id: entryId});
    }


    render() {

        return (
        <View>
            <ScrollView>
                { !this.state.fetching &&  this.entries().map((entry) => {

                    return (
                        <TouchableHighlight key={entry.id}>
                        <View  >
                            <Text>{entry.name}</Text>
                            <TouchableHighlight onPress={(entryId ) => this.handleChange(entry.id)}><Text>{entry.status}</Text></TouchableHighlight>
                            <Text>---------------------------</Text>

                        </View>
                        </TouchableHighlight>
                    )
                    }

                    )
                }
                {this.state.fetching ? <Text>Searching </Text> : null }
            </ScrollView>


        </View>
    )}
}

function mapStateToProps(state) {

    return {entries: state.default.entries };
}

function mapDispatchToProps(dispatch) {
    return {actions: bindActionCreators(actions,dispatch)};
}

export default connect(mapStateToProps, mapDispatchToProps)(Overview);

点击状态({entry.status})时,我打开另一个场景详情.js:

class Detail extends Component {

    constructor(props) {
        super(props);
        this.state = {}
    }

    componentWillMount() {
        this.setState({
            entry: this.props.entries[this.props.id]
        })
    }

    patchEntry(newStatus) {
        console.log("Details: patchEntry with " + this.props.id +" and " + newStatus );
        this.props.actions.patchEntry(this.props.id, newStatus);
    }

    render() {
        return (
            <View>
                <Text>{this.state.entry.name}</Text>

                <TouchableHighlight onPress={() => this.patchEntry('done')}><Text>Mark done</Text></TouchableHighlight>
                <TouchableHighlight onPress={() => this.patchEntry('cancelled')}><Text>Mark cancelled</Text></TouchableHighlight>
            </View>
        )
    }
}



function mapStateToProps(state) {
    console.log(state);
    return {entries: state.default.entries };
}


function mapDispatchToProps(dispatch) {
    return {actions: bindActionCreators(actions,dispatch)};
}

export default connect( mapStateToProps, mapDispatchToProps)(Detail);

当我按下一个TouchableHighlights时,我有一个动作和一个减速器被称为完全正常。我甚至在日志中看到输出整个状态时状态发生了变化。

但我的问题是,一旦我从Detail场景中回来(pop),我如何在Overview场景中刷新状态?

如果您需要更多信息,请告诉我,但在我编写完整的应用程序时,重现应该很简单。只需克隆,npm install并运行它。

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:1)

我快速查看了您的代码,以下是一些建议/信息。

Detail.js文件中,您将在安装组件后设置状态。 当您更新您的redux商店并获得刷新的道具时,它不会更新您的UI,因为它反映了您的状态,并且您的状态不会获得新值,因为您只是在componentWillMount方法上设置它。查看更多信息here in the docs

对于您来说,何时使用React组件的状态似乎也不是很清楚。 在此示例中,从Detail.js文件开始,您根本不需要组件的状态。您可以直接从属性计算该值。

例如:

render() {
  const entry = this.props.entries[this.props.id];
  return (
    <View>
      <Text>{entry.name}</Text>

      <TouchableHighlight onPress={() => this.patchEntry('done')}><Text>Mark done</Text></TouchableHighlight>
      <TouchableHighlight onPress={() => this.patchEntry('cancelled')}><Text>Mark cancelled</Text></TouchableHighlight>
    </View>
  )
}

您甚至可以在mapStateToProps功能中执行此操作。更多信息here

例如:

function mapStateToProps(state, ownProps) {
  return {
    entries: state.default.entries,
    entry: state.default.entries[ownProps.id],
  };
}

对于正在更新的UI,您的Overview.js文件似乎没问题,因为它的渲染方法反映的是props,而不是它的状态。

更新06/27

我刚检查了您的reducers,您可能还有一些修复方法。

case ENTRY_PATCHING:
  let patchedEntries = state.entries;
  patchedEntries[action.data.entryId].status = action.data.newStatus;

  return {...state,
    entries: patchedEntries
  }

在这个减速器中你会改变你的状态,你不能这样做。 redux商店不能变异。您可以在http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html

查看有关详细信息

所以,修复示例:

case ENTRY_PATCHING:
  const patchedEntry = {
    ...state.entries[action.data.entryId],
    status: action.data.newStatus
  }

  return {
    ...state,
    entries: {
      ...state.entries,
      [action.data.entryId]: patchedEntry,
    }
  }