0

Alright all of you React Pros out there. I have been struggling to wrap my head around this one for a while now. I have a database that has an array of objects that have arrays nested inside of them.

Initial state looks something like this...

const initialState = [{

    id: '',
    mainContent:[ 
        {
            title: "",
            content: []            
        },       
    ],            
    sideContent:[ 
        {
            title: "",
            content: []
        },       
    ],        
    pageTitle: ""

}]

With some content it is something along the lines of

const initialState = [{

    id: '123',
    mainContent:[ 
        {
            title: "About",
            content: ['something', 'something else', 'other stuff', 'blah blah blah']            
        }, 
        {
            title: "Something else",
            content: ['something', 'something else', 'other stuff', 'blah blah blah']            
        },      
    ],            
    sideContent:[ 
        {
            title: "About",
            content: ['something', 'something else', 'other stuff', 'blah blah blah']            
        }, 
        {
            title: "Something else",
            content: ['something', 'something else', 'other stuff', 'blah blah blah']            
        },      
    ],        
    pageTitle: "The main page title"

}]

I am trying to create a form where the person can edit the content of each item using useReducer. The page title seems to be working just fine with my form and useReducer. However when I try to map through the main content to be able to update any of its data I can display the mapped data but cant seem to figure out how to edit the data.

Form for the page title

       <form className='form' onSubmit={onSubmit}>

            <input
                type='text'
                placeholder='pageTitle'
                value={state.pageTitle}
                onChange={(e) =>
                    dispatch({
                    type: 'page-title',
                    fieldName: 'pageTitle',
                    payload: e.currentTarget.value,
                    })
                }
            />
        </form>

Mapping for the main content to display

            {state.mainContent.map((event,index) => (
                
                <input
                    key={index}
                    type='text'
                    placeholder='main content'
                    value={event.title}
                    onChange={(e) =>
                        dispatch({
                        type: 'main-content',
                        fieldName: {} ,
                        payload: e.currentTarget.value,
                        })
                        
                    }
                    
                />
                
            ))}

Reducer Code...

function editReducer(state, action) {
    
    switch (action.type) {
        case 'page-title': {
            return {
                ...state,
                [action.fieldName]: action.payload,
            };
        }
        case 'main-content': {
            return {
                ...state,
                
                mainContent: [{
                    ...state.mainContent,
                    title: action.payload,   
                }]
            };
        }
        case 'OnSuccess':  
            return {  
                setLoading: false,
                
                pageTitle: action.payload.pageTitle, 
                mainContent: action.payload.mainContent,
                sideContent: action.payload.sideContent,

                error: ''  
            }  
        case 'OnFailure':  
            return {  
                loading: false,                  
                error: 'Something went wrong'  
            } 
      default:
        return state;
    }
}

I have found that if I hard code an array value into my reducer I seem to be able to edit the information but it only applies to whatever location is hard coded.

Thank you in advance for all assistance.

1 Answers1

0

In your initial object, mainContent is an array, but in the reducer, you're treating it as an object.

mainContent: {
  ...state.mainContent,
  title: action.payload,   
}

You'll want to target the specific object in the mainContent array. Either assign each one an ID and rebuild the array in the reducer, or create a child component for each item and bubble up a state update.

GAntoine
  • 1,265
  • 2
  • 16
  • 28
  • Thank you for offering some insight. I am a brand new coder ( have been at it for about 3 months... ) I don't fully understand how to do what you are suggesting can you break it down please or if there is a way I could connect with you I would greatly appreciate any advice you could offer. – JustinMcDonald Jul 01 '21 at 20:54