{"id":3580,"date":"2023-03-09T15:27:22","date_gmt":"2023-03-09T08:27:22","guid":{"rendered":"https:\/\/www.bagi2info.com\/?p=3580"},"modified":"2023-03-10T01:43:26","modified_gmt":"2023-03-09T18:43:26","slug":"react-native-aplikasi-todo-menggunakan-asyncstorage","status":"publish","type":"post","link":"https:\/\/www.bagi2info.com\/en\/react-native-crud-todo-app-using-asyncstorage\/","title":{"rendered":"React Native - CRUD Todo App Using AsyncStorage"},"content":{"rendered":"\r\n<p>This article will discuss a simple TodoApp application using simple storage, namely <strong>AsyncStorage<\/strong>.<\/p>\r\n\r\n\r\n\r\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\r\n<p><\/p>\r\n<cite>AsyncStorage is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage. It is recommended that you use an abstraction on top of AsyncStorage instead of AsyncStorage directly for anything more than light usage since it operates globally.<\/cite><\/blockquote>\r\n\r\n\r\n\r\n<p>Based on the explanation from the website <a href=\"https:\/\/reactnative.dev\/docs\/asyncstorage\" title=\"\">React Native<\/a> it can be interpreted that <strong>AsyncStorage<\/strong>is a key value storage system which is unencrypted, asynchronous, persistent, and global for the application. It should be used instead of <strong>LocalStorage<\/strong>. It is recommended that you use the above abstraction AsyncStorage instead of AsyncStorage directly for anything but light use as it operates globally.<\/p>\r\n\r\n\r\n\r\n<p>So <strong>AsyncStorage<\/strong>is non-encrypted storage, so it is not recommended to be used for applications with complex processes, We can use it as simple storage such as mobile application configurations, but remember if you want to store crucial information better added encryption first.<\/p>\r\n\r\n\r\n\r\n<p><\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large is-resized is-style-default\"><a href=\"https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093-461x1024.jpg\" alt=\"\" class=\"wp-image-4147\" width=\"231\" height=\"512\" srcset=\"https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093-461x1024.jpg 461w, https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093-135x300.jpg 135w, https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093-768x1707.jpg 768w, https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093-691x1536.jpg 691w, https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093-922x2048.jpg 922w, https:\/\/www.bagi2info.com\/wp-content\/uploads\/2023\/03\/1678344769093.jpg 1080w\" sizes=\"auto, (max-width: 231px) 100vw, 231px\" \/><\/a><\/figure>\r\n\r\n\r\n\r\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.bagi2info.com\/en\/react-native-crud-todo-app-using-asyncstorage\/#1_Appjs\" >1. App.js<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.bagi2info.com\/en\/react-native-crud-todo-app-using-asyncstorage\/#2_TodoListjs\" >2. TodoList.js<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.bagi2info.com\/en\/react-native-crud-todo-app-using-asyncstorage\/#3_Dependencies\" >3. Dependencies<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"1_Appjs\"><\/span>1. App.js<span class=\"ez-toc-section-end\"><\/span><\/h2>\r\n\r\n\r\n\r\n<pre title=\"App.js\" class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx line-numbers\">import React, { Component } from 'react';\r\nimport {\r\n  Text,\r\n  View,\r\n  TextInput,\r\n  StyleSheet,\r\n  StatusBar,\r\n  Dimensions,\r\n  Platform,\r\n  ScrollView,\r\n  ActivityIndicator,\r\n  AsyncStorage,\r\n} from 'react-native';\r\n\r\nimport 'react-native-get-random-values';\r\nimport { v1 as uuidv1 } from 'uuid';\r\nimport { LinearGradient } from 'expo-linear-gradient';\r\n\r\nconst { height, width } = Dimensions.get('window');\r\n\r\nimport TodoList from '.\/TodoList';\r\n\r\nexport default class App extends Component {\r\n  state = {\r\n    newTodoItem: '',\r\n    dataIsReady: false,\r\n    todos: {}, \/\/ add this\r\n  };\r\n  newTodoItemController = (textValue) =&gt; {\r\n    this.setState({\r\n      newTodoItem: textValue,\r\n    });\r\n    console.log('data', this.state);\r\n  };\r\n  componentDidMount = () =&gt; {\r\n    this.loadTodos();\r\n  };\r\n\r\n  loadTodos = async () =&gt; {\r\n    try {\r\n      const getTodos = await AsyncStorage.getItem('todos');\r\n      const parsedTodos = JSON.parse(getTodos);\r\n      this.setState({ dataIsReady: true, todos: parsedTodos || {} });\r\n    } catch (err) {\r\n      console.log(err);\r\n    }\r\n  };\r\n\r\n  saveTodos = (newToDos) =&gt; {\r\n    AsyncStorage.setItem('todos', JSON.stringify(newToDos));\r\n  };\r\n  addTodo = () =&gt; {\r\n    const { newTodoItem } = this.state;\r\n\r\n    if (newTodoItem !== '') {\r\n      this.setState((prevState) =&gt; {\r\n        const ID = uuidv1();\r\n        const newToDoObject = {\r\n          [ID]: {\r\n            id: ID,\r\n            isCompleted: false,\r\n            textValue: newTodoItem,\r\n            createdAt: Date.now(),\r\n          },\r\n        };\r\n        const newState = {\r\n          ...prevState,\r\n          newTodoItem: '',\r\n          todos: {\r\n            ...prevState.todos,\r\n            ...newToDoObject,\r\n          },\r\n        };\r\n\r\n        this.saveTodos(newState.todos); \/\/ add this\r\n        return { ...newState };\r\n      });\r\n    }\r\n  };\r\n\r\n  deleteTodo = (id) =&gt; {\r\n    this.setState((prevState) =&gt; {\r\n      const todos = prevState.todos;\r\n      delete todos[id];\r\n      const newState = {\r\n        ...prevState,\r\n        ...todos,\r\n      };\r\n      this.saveTodos(newState.todos); \/\/ add this\r\n      return { ...newState };\r\n    });\r\n  };\r\n\r\n  inCompleteTodo = (id) =&gt; {\r\n    this.setState((prevState) =&gt; {\r\n      const newState = {\r\n        ...prevState,\r\n        todos: {\r\n          ...prevState.todos,\r\n          [id]: {\r\n            ...prevState.todos[id],\r\n            isCompleted: false,\r\n          },\r\n        },\r\n      };\r\n      this.saveTodos(newState.todos); \/\/ add this\r\n      return { ...newState };\r\n    });\r\n  };\r\n\r\n  completeTodo = (id) =&gt; {\r\n    this.setState((prevState) =&gt; {\r\n      const newState = {\r\n        ...prevState,\r\n        todos: {\r\n          ...prevState.todos,\r\n          [id]: {\r\n            ...prevState.todos[id],\r\n            isCompleted: true,\r\n          },\r\n        },\r\n      };\r\n      this.saveTodos(newState.todos); \/\/ add this\r\n      return { ...newState };\r\n    });\r\n  };\r\n  updateTodo = (id, textValue) =&gt; {\r\n    this.setState((prevState) =&gt; {\r\n      const newState = {\r\n        ...prevState,\r\n        todos: {\r\n          ...prevState.todos,\r\n          [id]: {\r\n            ...prevState.todos[id],\r\n            textValue: textValue,\r\n          },\r\n        },\r\n      };\r\n      this.saveTodos(newState.todos); \/\/ add this\r\n      return { ...newState };\r\n    });\r\n  };\r\n  render() {\r\n    const { newTodoItem, dataIsReady, todos } = this.state;\r\n\r\n    if (!dataIsReady) {\r\n      return &lt;ActivityIndicator \/&gt;;\r\n    }\r\n\r\n    return (\r\n      &lt;LinearGradient style={styles.container} colors={['#DA4453', '#89216B']}&gt;\r\n        &lt;StatusBar barStyle=\"light-content\" \/&gt;\r\n\r\n        &lt;Text style={styles.appTitle}&gt;Todo App{'\\n'}Using AsyncStorage&lt;\/Text&gt;\r\n        &lt;View style={styles.card}&gt;\r\n          &lt;TextInput\r\n            style={styles.input}\r\n            placeholder={'Add an item!'}\r\n            value={newTodoItem}\r\n            onChangeText={this.newTodoItemController}\r\n            placeholderTextColor={'#999'}\r\n            returnKeyType={'done'}\r\n            autoCorrect={false}\r\n            onSubmitEditing={this.addTodo}\r\n          \/&gt;\r\n          &lt;ScrollView contentContainerStyle={styles.listContainer}&gt;\r\n            {Object.values(todos).map((todo) =&gt; (\r\n              &lt;TodoList\r\n                key={todo.id}\r\n                {...todo}\r\n                deleteTodo={this.deleteTodo}\r\n                inCompleteTodo={this.inCompleteTodo}\r\n                completeTodo={this.completeTodo}\r\n                updateTodo={this.updateTodo} \/\/ add this\r\n              \/&gt;\r\n            ))}\r\n          &lt;\/ScrollView&gt;\r\n        &lt;\/View&gt;\r\n      &lt;\/LinearGradient&gt;\r\n    );\r\n  }\r\n}\r\n\r\nconst styles = StyleSheet.create({\r\n  container: {\r\n    flex: 1,\r\n    alignItems: 'center',\r\n    backgroundColor: '#f23657',\r\n  },\r\n  appTitle: {\r\n    color: '#fff',\r\n    fontSize: 36,\r\n    marginTop: 60,\r\n    marginBottom: 30,\r\n    fontWeight: '300',\r\n    textAlign: 'center',\r\n  },\r\n  card: {\r\n    backgroundColor: '#fff',\r\n    flex: 1,\r\n    width: width - 25,\r\n    borderTopLeftRadius: 10,\r\n    borderTopRightRadius: 10,\r\n    ...Platform.select({\r\n      ios: {\r\n        shadowColor: 'rgb(50,50,50)',\r\n        shadowOpacity: 0.5,\r\n        shadowRadius: 5,\r\n        shadowOffset: {\r\n          height: -1,\r\n          width: 0,\r\n        },\r\n      },\r\n      android: {\r\n        elevation: 5,\r\n      },\r\n    }),\r\n  },\r\n  input: {\r\n    padding: 20,\r\n    borderBottomColor: '#bbb',\r\n    borderBottomWidth: 1,\r\n    fontSize: 24,\r\n  },\r\n  listContainer: {\r\n    alignItems: 'center',\r\n  },\r\n});\r\n<\/code><\/pre>\r\n\r\n\r\n\r\n<p>The App.js file is the main part of the application, there are various CRUD functions, such as <strong>addTodo, deleteTodo, updateTodo<\/strong> and so on. Here is the function to save directly to <strong>AsyncStorage<\/strong> with the key name <strong>todos<\/strong>.<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">  saveTodos = (newToDos) => {\r\n    AsyncStorage.setItem('todos', JSON.stringify(newToDos));\r\n  };<\/code><\/pre>\r\n\r\n\r\n\r\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"2_TodoListjs\"><\/span>2. TodoList.js<span class=\"ez-toc-section-end\"><\/span><\/h2>\r\n\r\n\r\n\r\n<pre title=\"TodoList.js\" class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx line-numbers\">import React, { Component } from 'react';\r\nimport {\r\n  View,\r\n  Text,\r\n  StyleSheet,\r\n  TouchableOpacity,\r\n  Dimensions,\r\n  TextInput,\r\n} from 'react-native';\r\n\r\nconst { height, width } = Dimensions.get('window');\r\nimport PropTypes from 'prop-types';\r\n\r\nclass TodoList extends Component {\r\n  constructor(props) {\r\n    super(props);\r\n\r\n    this.state = {\r\n      isEditing: false,\r\n      todoValue: props.textValue,\r\n    };\r\n  }\r\n  \/\/ in our class before we define state\r\n  static propTypes = {\r\n    textValue: PropTypes.string.isRequired,\r\n    isCompleted: PropTypes.bool.isRequired,\r\n    deleteTodo: PropTypes.func.isRequired,\r\n    id: PropTypes.string.isRequired,\r\n    inCompleteTodo: PropTypes.func.isRequired,\r\n    completeTodo: PropTypes.func.isRequired,\r\n    updateTodo: PropTypes.func.isRequired,\r\n  };\r\n\r\n  state = {\r\n    todoValue: '',\r\n    isEditing: false,\r\n  };\r\n\r\n  toggleItem = () =&gt; {\r\n    const { isCompleted, inCompleteTodo, completeTodo, id } = this.props;\r\n    if (isCompleted) {\r\n      inCompleteTodo(id);\r\n    } else {\r\n      completeTodo(id);\r\n    }\r\n  };\r\n\r\n  startEditing = () =&gt; {\r\n    this.setState({\r\n      isEditing: true,\r\n    });\r\n  };\r\n\r\n  finishEditing = () =&gt; {\r\n    this.setState({\r\n      isEditing: false,\r\n    });\r\n  };\r\n  controlInput = (textValue) =&gt; {\r\n    this.setState({ todoValue: textValue });\r\n  };\r\n  finishEditing = () =&gt; {\r\n    const { todoValue } = this.state;\r\n    const { id, updateTodo } = this.props;\r\n    updateTodo(id, todoValue);\r\n    this.setState({\r\n      isEditing: false,\r\n    });\r\n  };\r\n  render() {\r\n    const { isEditing, todoValue } = this.state;\r\n    const { textValue, id, deleteTodo, isCompleted } = this.props;\r\n\r\n    return (\r\n      &lt;View style={styles.container}&gt;\r\n        &lt;View style={styles.rowContainer}&gt;\r\n          &lt;TouchableOpacity onPress={this.toggleItem}&gt;\r\n            &lt;View\r\n              style={[\r\n                styles.circle,\r\n                isCompleted ? styles.completeCircle : styles.incompleteCircle,\r\n              ]}&gt;&lt;\/View&gt;\r\n          &lt;\/TouchableOpacity&gt;\r\n          {isEditing ? (\r\n            &lt;TextInput\r\n              value={todoValue}\r\n              style={[\r\n                styles.text,\r\n                styles.input,\r\n                isCompleted ? styles.strikeText : styles.unstrikeText,\r\n              ]}\r\n              multiline={true}\r\n              returnKeyType={'done'}\r\n              onBlur={this.finishEditing}\r\n              onChangeText={this.controlInput}\r\n            \/&gt;\r\n          ) : (\r\n            &lt;Text\r\n              style={[\r\n                styles.text,\r\n                isCompleted ? styles.strikeText : styles.unstrikeText,\r\n              ]}&gt;\r\n              {textValue}\r\n            &lt;\/Text&gt;\r\n          )}\r\n        &lt;\/View&gt;\r\n        {isEditing ? (\r\n          &lt;View style={styles.buttons}&gt;\r\n            &lt;TouchableOpacity onPressOut={this.finishEditing}&gt;\r\n              &lt;View style={styles.buttonContainer}&gt;\r\n                &lt;Text style={styles.buttonText}&gt;\u2705&lt;\/Text&gt;\r\n              &lt;\/View&gt;\r\n            &lt;\/TouchableOpacity&gt;\r\n          &lt;\/View&gt;\r\n        ) : (\r\n          &lt;View style={styles.buttons}&gt;\r\n            &lt;TouchableOpacity onPressOut={this.startEditing}&gt;\r\n              &lt;View style={styles.buttonContainer}&gt;\r\n                &lt;Text style={styles.buttonText}&gt;\u270f&lt;\/Text&gt;\r\n              &lt;\/View&gt;\r\n            &lt;\/TouchableOpacity&gt;\r\n            &lt;TouchableOpacity onPressOut={() =&gt; deleteTodo(id)}&gt;\r\n              &lt;View style={styles.buttonContainer}&gt;\r\n                &lt;Text style={styles.buttonText}&gt;\u274c&lt;\/Text&gt;\r\n              &lt;\/View&gt;\r\n            &lt;\/TouchableOpacity&gt;\r\n          &lt;\/View&gt;\r\n        )}\r\n      &lt;\/View&gt;\r\n    );\r\n  }\r\n}\r\n\r\nconst styles = StyleSheet.create({\r\n  container: {\r\n    width: width - 50,\r\n    borderBottomColor: '#bbb',\r\n    borderBottomWidth: StyleSheet.hairlineWidth,\r\n    flexDirection: 'row',\r\n    alignItems: 'center',\r\n    justifyContent: 'space-between',\r\n    backgroundColor: '#fff',\r\n  },\r\n\r\n  input: {\r\n    marginVertical: 15,\r\n    width: width \/ 2,\r\n    paddingBottom: 5,\r\n  },\r\n  text: {\r\n    fontWeight: '500',\r\n    fontSize: 18,\r\n    marginVertical: 20,\r\n  },\r\n  \/\/ Styles\r\n  circle: {\r\n    width: 30,\r\n    height: 30,\r\n    borderRadius: 15,\r\n    \/\/ remove borderColor property from here\r\n    borderWidth: 3,\r\n    marginRight: 20,\r\n  },\r\n  completeCircle: {\r\n    borderColor: '#bbb',\r\n  },\r\n  incompleteCircle: {\r\n    borderColor: '#DA4453',\r\n  },\r\n\r\n  rowContainer: {\r\n    flexDirection: 'row',\r\n    width: width \/ 2,\r\n    alignItems: 'center',\r\n    justifyContent: 'space-between',\r\n  },\r\n  buttons: {\r\n    flexDirection: 'row',\r\n  },\r\n  buttonContainer: {\r\n    marginVertical: 10,\r\n    marginHorizontal: 10,\r\n  },\r\n\r\n  \/\/ Styles\r\n\r\n  strikeText: {\r\n    color: '#bbb',\r\n    textDecorationLine: 'line-through',\r\n  },\r\n  unstrikeText: {\r\n    color: '#29323c',\r\n  },\r\n});\r\n\r\nexport default TodoList;<\/code><\/pre>\r\n\r\n\r\n\r\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"3_Dependencies\"><\/span>3. Dependencies<span class=\"ez-toc-section-end\"><\/span><\/h2>\r\n\r\n\r\n\r\n<pre title=\"Dependencies\" class=\"wp-block-code\"><code lang=\"json\" class=\"language-json line-numbers\">{\r\n  \"dependencies\": {\r\n    \"uuid\": \"9.0.0\",\r\n    \"prop-types\": \"*\",\r\n    \"expo-constants\": \"~13.2.4\",\r\n    \"@expo\/vector-icons\": \"^13.0.0\",\r\n    \"expo-linear-gradient\": \"~11.4.0\",\r\n    \"react-native-dropdownalert\": \"*\",\r\n    \"react-native-get-random-values\": \"~1.8.0\"\r\n  }\r\n}<\/code><\/pre>\r\n\r\n\r\n\r\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\r\n\r\n\r\n\r\n<p>Link : <a href=\"https:\/\/snack.expo.dev\/@rudiahmad\/react-native---todo-app-using-asyncstorage\" title=\"\">https:\/\/snack.expo.dev\/@rudiahmad\/react-native&#8212;todo-app-using-asyncstorage<\/a><\/p>\r\n\r\n\r\n\r\n<p>The sample source has been modified to run directly through Snack, including: adding <strong>react-native-get-random-values<\/strong> to use uuid, adding the addTodo function in the <strong>onSubmitEditing= property {this.addTodo} <\/strong>on TextInput, and minor syntax fixes<\/p>\r\n\r\n\r\n\r\n<p><\/p>\r\n\r\n\r\n\r\n<p>Source : https:\/\/blog.eduonix.com\/mobile-programming\/learn-build-react-native-todo-application-part-1\/<\/p>\r\n","protected":false},"excerpt":{"rendered":"<p>This article will discuss a simple TodoApp application using simple storage, namely AsyncStorage. AsyncStorage is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":4149,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[173],"tags":[],"class_list":["post-3580","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react-native"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/posts\/3580","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/comments?post=3580"}],"version-history":[{"count":10,"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/posts\/3580\/revisions"}],"predecessor-version":[{"id":4169,"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/posts\/3580\/revisions\/4169"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/media\/4149"}],"wp:attachment":[{"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/media?parent=3580"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/categories?post=3580"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bagi2info.com\/en\/wp-json\/wp\/v2\/tags?post=3580"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}