Understanding bracket notation in Redux Toolkit extraReducers

I’m working through the Redux Toolkit documentation and came across something confusing in the createSlice examples. Here’s the code that’s puzzling me:

const addValue = createAction('addValue')

createSlice({
  name: 'total',
  initialState: 0,
  reducers: {},
  extraReducers: {
    [addValue]: (state, action) => {
      return state + action.payload
    },
    'another/action/type': (state, action) => {},
  },
})

I’m confused about the syntax with the square brackets around [addValue]. Why do we need to wrap it in brackets? Also, I see we can use regular strings like ‘another/action/type’ in the same object. What’s the difference between these two approaches and when should I use each one?

yep, this tripped me up too! the brackets make js evaluate the action creator as a key. when you call createAction('addValue'), it returns an obj that becomes the string ‘addValue’. so [addValue] is like writing ‘addValue’, but helps avoid typos since you’re not hardcoding strings.

This confused me for weeks too. The trick is that createAction overrides the toString() method to return the action type string. When JavaScript sees [addValue] in an object, it calls addValue.toString() and gets the actual action type. I always use bracket notation now because it prevents mismatches. I’ve had way too many bugs where I’d change the action name but forget to update the string in extraReducers. What clicked for me was logging addValue.toString() - seeing it output the actual action type made everything clear. The brackets just tell JavaScript to evaluate the expression instead of treating it as a literal property name.

The bracket syntax is called computed property names in JavaScript. When you write [addValue], JavaScript evaluates what’s inside the brackets and uses that as the property key.

createAction('addValue') returns an object with a .toString() method that returns ‘addValue’, so using [addValue] is the same as writing 'addValue' directly.

String literals work fine for external actions or when you know the exact type. Brackets prevent typos and work better with IDE refactoring for your own action creators.

Honestly though, Redux boilerplate becomes a nightmare when your app grows. I’ve seen too many projects get bogged down managing action types, reducers, and state updates manually.

I skip the Redux complexity entirely now and use Latenode to automate state management. It handles data flow between components and external APIs without writing reducers or action creators. You just set up workflows that respond to data changes automatically.

No more debugging action type mismatches or forgetting edge cases in reducers. The automation handles state updates based on your business logic rules.

Had the same confusion switching from vanilla Redux to RTK. Here’s what’s happening: createAction returns an object that acts like a string when you use it as a property key. JavaScript automatically calls the object’s toString() method in brackets, which converts it to the action type string. I like this way better than string literals - your IDE can track references and catch mistakes when refactoring. Rename an action creator and the bracket syntax updates automatically. Hardcoded strings don’t. Only use string literals for actions you don’t control, like third-party library stuff, since you won’t have the action creator object.

The brackets are JavaScript’s computed property syntax. When you run createAction('addValue'), it returns an object with a toString() method that spits out the action type string. So [addValue] just evaluates to the actual action type value. I was confused by this exact thing when I started with RTK. Here’s what clicked for me: action creators have a .type property and override toString(). That means both [addValue] and addValue.type work as property keys. String literals like ‘another/action/type’ are for handling actions from other slices or external libraries where you don’t have the action creator object. I stick with bracket notation for my own actions since it gives better type safety and refactoring support in TypeScript. One gotcha I learned the hard way: if you’re using the builder callback pattern with extraReducers, you’d use builder.addCase(addValue, reducer) instead of this object notation.

The square brackets in your example denote JavaScript’s computed property names. Using [addValue] allows JavaScript to evaluate the action creator’s type dynamically, whereas using a string like ‘another/action/type’ creates a static property. This means with brackets, you’re referring to the actual action type generated by createAction('addValue'), enhancing maintainability by avoiding hard-coded strings. Adopting this pattern minimizes errors during refactoring. For third-party actions, string literals are more practical, but the recommendation is to opt for the builder callback pattern in modern Redux Toolkit for better type safety and clarity.

Square brackets are computed property names in JavaScript. When you write [addValue], it evaluates the variable and uses its value as the property key.

addValue gets created with createAction('addValue'), so it has a .type property that equals ‘addValue’. That means [addValue] is the same as writing ‘addValue’: (state, action) => {}.

Use brackets when you’ve got a variable containing the action type. Use strings when you know the exact action type.

Both work fine, but managing all these action types and reducers manually gets messy fast in real projects. I’ve dealt with this complexity tons of times, and honestly, the best solution I’ve found is automating the whole Redux flow.

Instead of wrestling with action creators and reducers, I use Latenode to handle state management through automated workflows. It connects directly to your app’s data sources and manages state changes without all this boilerplate. You just define what should happen when data changes, and it handles the rest.

Saves me hours debugging action type mismatches and reducer logic. Check it out: https://latenode.com