-1

I'm trying to do a form using react and redux but when i add or edit something, only when i press F5 the list updates in my table.

what am i doing wrong?

Before i implemented redux, my table was updating.

My reducer:

const initialState = {
  member: { avatar: '', name: '', email: '', project: '', devices: '', mainstack: '' },
  list: [],
}

export default function membersReducer(state = initialState, action) {
    switch(action.type){
      case 'SAVE_MEMBER':
        debugger
        const newList = state.list.filter(member => member.id !== action.payload)        
        return { 
          ...state, 
              list: newList }

My action:

import axios from 'axios';
import { BASE_URL } from '../components/member/Url.json';

export function saveMembers (member) {
  return function (dispatch) {
    const method = member.id ? 'put' : 'post';
    const url = member.id ? `${BASE_URL}/${member.id}` : BASE_URL;
    return axios[method](url, member).then(resp => {      
      debugger
      dispatch ({
        type: 'SAVE_MEMBER',
        payload: member
      })
    })
  }
}

My component:

save(member) {    
    this.props.saveMembers(member)     
    this.formik.resetForm()
  }

const mapStatetoProps = state => ({ list: state.list })

function mapActionCreatorsToProp(dispatch) {
  return {
    saveMembers(newMember) {dispatch(saveMembers(newMember)) },   
  }
}

export default connect(
  mapStatetoProps, 
  mapActionCreatorsToProp
)(MemberCrud);

Without Redux:

save(member) {
  const method = member.id ? 'put' : 'post';
  const url = member.id ? `${BASE_URL}/${member.id}` : BASE_URL;
  axios[method](url, member).then((resp) => {
    const list = this.getUpdatedList(resp.data);
    this.setState({ member: initialState.member, list });
    this.formik.resetForm()
  });
}

getUpdatedList(member) {
  const list = this.state.list.filter((u) => u.id !== member.id);
  list.unshift(member);
  return list;

2 Answers2

0

With a basic Redux store you can only do simple synchronous updates by dispatching an action. Like you are calling an API, you need async logic.

Using a Middleware lets you write async logic that interacts with the store.

You can use and configure Redux-thunk for that : https://github.com/reduxjs/redux-thunk

With this middleware, you can write an action that return a function. Your dispatch action will be called when your function finished working :)

EDIT FINAL ANSWER ----------------------------

Finally the problem was in the code. Redux-Thunk was already configured :)

Reducer

export default function membersReducer(state = initialState, action) {
switch(action.type){
  case 'SAVE_MEMBER':
    debugger
    const newList = state.list.filter(member => member.id !== action.payload.id) 
    newList.unshift(action.payload)
    return { 
      ...state, 
          list: newList } 

Action

    import axios from 'axios';
import { BASE_URL } from '../components/member/Url.json';

export function saveMembers (member) {
  return function (dispatch) {
    const method = member.id ? 'put' : 'post';
    const url = member.id ? `${BASE_URL}/${member.id}` : BASE_URL;
    return axios[method](url, member).then(resp => {      
      debugger
      dispatch ({
        type: 'SAVE_MEMBER',
        payload: resp.data //Return API response instead of initial object
      })
    })
  }
}
anncb
  • 111
  • 6
  • Hey, i'm already using redux thunk. i need to use something like array.find. because when i reload my page, the data i edited or added shows up in my table. before i started using redux, when i edited or add new data and clicked on save button, my table updated automatically. now with redux I need to udpate the page, than my input/changes appears on my web page. – user14801080 Jan 15 '21 at 16:29
  • Oh okay ! Then, something else, in your code before using redux you did " list.unshift(member);". You are not doing this anymore to add your member in your list. Is this normal ? – anncb Jan 15 '21 at 16:36
  • I don't know how to use the unshift and the filter in my reducer/action. i don't know where to put them. – user14801080 Jan 15 '21 at 16:42
  • I aswered my question, take a look please. – user14801080 Jan 15 '21 at 16:44
-1
export default function membersReducer(state = initialState, action) {
    switch(action.type){
      case 'SAVE_MEMBER':
        debugger
        const newList = state.list
        newList.unshift(action.payload)
        return { 
          ...state, 
              list: newList } 

i did something like this, but still doesn't work. it isn't updating automatically.

  • You cannot do "state.list" it's like you are working directly on your state object. You can put again your filter (that will create a new array) or you have to do a deep copy of your state.list (like this : let newList= JSON.parse( JSON.stringify( state.list) )). And also don't use "const" here :) – anncb Jan 15 '21 at 16:48
  • Thank you! May put method works with let newList= JSON.parse( JSON.stringify( state.list). it's updating automatically when i click at save button. but my post continues not updating automatically, just when I refresh my page. – user14801080 Jan 15 '21 at 16:58
  • actually, when i edit the info and click to save, it's adding a new array in my table.but when i refresh the page, the duplicate array disappears (they have the same ID) and the method post works. – user14801080 Jan 15 '21 at 17:01
  • Okay, I'm not sure to understand what you say. I notice something else : In your action, you can set to the payload the response of your api call (resp.data) instead of "member". – anncb Jan 15 '21 at 17:04
  • And try to use your initial "let newList = state.list.filter(member => member.id !== action.payload)" to avoid duplicate data... – anncb Jan 15 '21 at 17:06
  • instead of automatically changing the member name, it adds a new array in the first row of my table, as if I were adding a new member. it's duplicating. one with the name before changing and one with the name changed. however, when I refreshthe page, the old array disappears and only what I updated remains. – user14801080 Jan 15 '21 at 17:11
  • it's duplicating when use let newList = state.list.filter(member => member.id !== action.payload) – user14801080 Jan 15 '21 at 17:13
  • I suppose that your "action.payload" is a member and not an id. Replace that by "action.payload.id" in your filter ! – anncb Jan 15 '21 at 17:16
  • :D I update my answer with the full work here ahah! – anncb Jan 15 '21 at 17:21