user1661286
user1661286

Reputation: 133

React how to convert string to object property

In a React project, I want to dynamically access an object property name using a string variable I pass through props. I am able to pass a value as string; however, when I try to use it to access the object property it doesn't work.

Here's an example:

const passedField = 'title'; // this comes from props
const book = { title: 'Sample title', content : 'some content' };
book.passedField; // returns undefined

I access title like this book.title

I want to access it like book.passedField but I get undefined on console.

How can I achieve this?

Upvotes: 0

Views: 14239

Answers (3)

AnonymousSB
AnonymousSB

Reputation: 3604

What you're using is called a dot notation property accessor. What you need to use is a bracket notation property accessor.

book.title and book['title'] are the same, which means you can assign title to a variable, and use the variable name instead like this.

const passedField = 'title';
book[passedField]; // same as book['title']

You might only be familiar with bracket notation with Arrays, like myArray[0], but they work with Objects too! (because Arrays in JavaScript are actually objects)

Solution

const books = [
  {
    title: 'The Art of War',
    contents: 'An ancient Chinese military treatise dating from the Spring and Autumn Period'
  },
  {
    title: 'Winnie the Pooh',
    contents: 'Pooh is naive and slow-witted, but he is also friendly, thoughtful, and steadfast.'
  }
]

class Book extends React.Component {
  constructor(props) {
    super(props);
    this.findBookByFilter = this.findBookByFilter.bind(this);
  }
  
  findBookByFilter() {
    let result = null
    if (books) {
      const {passedFilterField, filterText} = this.props;
      
      result = books.filter(book => {
        return book[passedFilterField].toLowerCase().includes(filterText.toLowerCase());
      }).map(book => <p>{book.title}</p>)
    }
    return result;
  }
  
  render () {
    return this.findBookByFilter();
  }
}

class App extends React.Component {
  render() {
    return (
      <Book
        passedFilterField='contents' 
        filterText='thoughtful'
      />
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Notes

  • I moved your {book && book.filter} logic to a function called findBookByFilter
  • I used includes instead of indexOf in the filter
  • I used destructuring assignment for this.props
  • I return the matched title, rather than <Link /> for demo purposes.

Documentation

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Upvotes: 4

francium
francium

Reputation: 2480

You can access object properties using book[passedField]

Upvotes: 1

Isaac
Isaac

Reputation: 12874

book.passedField will be returning undefined because there is no passedField in book. Instead use bracket notation as below

const book = { title: 'abc', pages: 350 };
const passedField = 'pages';

console.log(book[passedField])

Upvotes: 4

Related Questions