Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
556 views
in Technique[技术] by (71.8m points)

reactjs - Force React container to refresh data

In my React application, I have two distinct types of components: presentations and containers. It's roughly after Dan Abromov's "Presentational and Container Components", except I don't use Flux or Redux.

Now, I have the following structure:

UsersContainer
├── UsersListContainer
|   └── UsersListView
└── AddUserContainer

The UsersListContainer is responsible for loading data from some REST API, and if that succeeds, it delegates presenting that data to the UsersListView.

The AddUserContainer is responsible for adding a new user, again, by invoking an REST API. Now, when that was successful, I would like the UsersListContainer to refresh its data.

The best I can think of is this:

class AddUserContainer extends React.Component {
  render() {
    // Other UI elements omitted for brevity
    return (<button onClick={ e => props.onUserAdded() }>Add user</button>);
  }
}

class UsersListContainer extends React.Component {
  componentWillMount() {
    // start fetching data using window.fetch;
    // the promise callback will but retrieved data into this.state
  }
  render() {
    return (<table></table>);
  }
}

class UsersContainer extends React.Component {
  render() {
    const forceUpdate = this.setState({ ...this.state, refreshToken: Math.random() });
    // Other UI elements omitted for brevity
    <UsersListContainer key={ this.state.refreshToken } />
    <AddUserContainer onUserAdded={ forceUpdate } />
  }
}

But this approach feels like mis-using the key prop. Is there a better / more elegant way to do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Check out react-refetch, which provides a nice API for fetching, and allows you to implement the Presentational and Container Components pattern, without using Flux/Redux for API calls.

It also lets you handle loading and errored states, which is definitely necessary for a decent web application today.

In the example below, I got rid of UsersListContainer but moved AddUserContainer into UsersContainer as well. This makes your UsersListView the presentational component for UsersContainer. Feel free to change the naming as you wish. This is so that I can get the refreshUsers prop to pass into AddUserContainer.

// UsersContainer.js

const Container = ({ usersFetch, refreshUsers }) => {
    if (userFetch.pending) {
        return <LoadingDisplay />
    } else if (usersFetch.rejected) {
        return <ErrorDisplay error={ usersFetch.reason } />
    } else if (usersFetch.fulfilled) {
        return (
            <UsersListView users={ usersFetch.value } />
            <AddUserContainer handleAddUser={ refreshUsers } />
        );
    }
};

const refetch = (props) => {
    const usersFetch = `/api/users`;

    return {
        usersFetch: usersFetch,
        refreshUsers: () => ({
            usersFetch: { ...usersFetch, force: true, refreshing: true }
        }),
    };
};

export default connect(refetch)(Container);

Check out the documentation for more examples. I personally prefer to use react-refetch for API-heavy applications, rather than implementing the calls in Redux.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...