简体   繁体   中英

React: how to “remember” initial props

I am playing around with React and Redux and built a simple todo-app. Now, I want to make a save button for user, that gonna save changes made to the todos if there were any (ie changing text). So the save button needs to know somehow if there were any changes made to the todos.

For example, initially we have these todos that are coming from Redux:

const todos = [
    {
        id: 0,
        text: 'Learn Redux',
    },
    {
        id: 1,
        text: 'Learn React',
    }
]

But the user made some changes to the todos!

const todos = [
    {
        id: 0,
        text: 'Eat a cookie',
    },
    {
        id: 1,
        text: 'Read a book',
    }
]

So my question is, how can I detect those changes?

There are many ways you can do this. You could use the constructor to remember initial props by doing something like:

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

Since you are using redux you could also handle this in a middleware who's main job is to check and see if the data you are trying to save is different then the value that is kept in the store. Here are the docs for middleware in redux.

You can dispatch an action to notify the save button whenever you dispatch an action changing the todos. Also if your reducer is pure, it will not mutate the previous state, so it is easy to know whether the todos has changed or not. if the object reference is different, it is changed.

Since the point of this is to learn best practices around React + Redux, the best way to do this would be to have your props be the todos coming from your Redux state, and then have your component state be whatever it is currently being mutated to. So in your above example,

Redux state which feeds to component props is

const todos = [
    {
        id: 0,
        text: 'Learn Redux',
    },
    {
        id: 1,
        text: 'Learn React',
    }
]

And then component state is

const todos = [
    {
        id: 0,
        text: 'Eat a cookie',
    },
    {
        id: 1,
        text: 'Read a book',
    }
]

In your constructor you would do something like (_ is a library like lodash ):

constructor(props) {
   super(props);
   this.state = { todos: _.clone(props.todos) };
}

the component would only ever manipulate this.state.todos and then when you are ready to save, you can compare this.state.todos to this.props.todos to see how things have changed.

Then you dispatch the action to save the todos to your redux state (ex: save(this.state.todos)

Your component should be listening to Redux state via a library like reselect and its props will be updated.

if you are using thunk middleware then you may write an action creater like

const getTodos = (getState)=>getState().todos;
const saveAction = newTodos=> async(dispatch, getState)=>{
    const initialTodos = getTodos(getState()); 
    await dispatch('SAVE_ACTION', newTodos);
    const finalTodos = getTodos(getState());
    if(initialTodos !== finalTodos){
           dispatch('UPDATE_TODOS_IN_SERVER', finalTodos);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM