Next.js

Integrate Strapi with Next.js.

开始使用 Next.js

本集成指南遵循 快速入门指南,并假设您已完全完成“动手”路径。您应该能够通过浏览 URL http://localhost:1337/api/restaurants 来使用该 API。

如果您尚未阅读快速入门指南,则使用 Next.js 请求 Strapi API 的方式保持不变,只是您不会获取相同的内容。

创建 Next.js 应用

创建一个基本的 Next.js 应用程序。

bash
yarn
bash
yarn create next-app nextjs-app

使用 HTTP 客户端

有许多 HTTP 客户端可用,但在本文档中我们将使用 AxiosFetch

bash
axios
bash
yarn add axios

如果您在使用 Axios 时收到 localhost 错误,但通过将 localhost 替换为 127.0.0.1,您的请求可以正常工作,请确保这不是 CORS 问题(请参阅 axios GitHub 中的更多详细信息)。

GET 请求您的集合类型

restaurant 集合类型执行 GET 请求以获取您的所有餐厅。

确保您已为 restaurant 集合类型激活 find 权限。

js
axios
js
import axios from 'axios'

axios.get('http://localhost:1337/api/restaurants').then((response) => {
  console.log(response.data)
})
Example response
json
{
  "data": [
    {
      "id": 1,
      "attributes": {
        "name": "Biscotte Restaurant",
        "description": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers.",
        "createdAt": "2022-07-31T09:14:12.569Z",
        "updatedAt": "2022-07-31T09:14:12.569Z",
        "publishedAt": "2022-07-31T09:14:12.569Z"
      }
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "pageSize": 25,
      "pageCount": 1,
      "total": 1
    }
  }
}

Example

./pages/index.js

axios
js
import axios from 'axios'

function Home({ restaurants, error }) {
  if (error) {
    return (
      <div>
        An error occured:
        {error.message}
      </div>
    )
  }
  return (
    <ul>
      {restaurants.data.map(restaurant => (
        <li key={restaurant.id}>{restaurant.attributes.Name}</li>
      ))}
    </ul>
  )
}

Home.getInitialProps = async (ctx) => {
  try {
    const res = await axios.get('http://localhost:1337/api/restaurants')
    const restaurants = res.data
    return { restaurants }
  }
  catch (error) {
    return { error }
  }
}

export default Home
fetch
js
function Home({ restaurants, error }) {
  if (error) {
    return (
      <div>
        An error occured:
        {error.message}
      </div>
    )
  }
  return (
    <ul>
      {restaurants.data.map(restaurant => (
        <li key={restaurant.id}>{restaurant.attributes.Name}</li>
      ))}
    </ul>
  )
}
Home.getInitialProps = async (ctx) => {
  try {
    // Parses the JSON returned by a network request
    const parseJSON = resp => (resp.json ? resp.json() : resp)
    // Checks if a network request came back fine, and throws an error if not
    const checkStatus = (resp) => {
      if (resp.status >= 200 && resp.status < 300) {
        return resp
      }

      return parseJSON(resp).then((resp) => {
        throw resp
      })
    }

    const headers = {
      'Content-Type': 'application/json',
    }

    const restaurants = await fetch('http://localhost:1337/api/restaurants', {
      method: 'GET',
      headers,
    })
      .then(checkStatus)
      .then(parseJSON)

    return { restaurants }
  }
  catch (error) {
    return { error }
  }
}

export default Home

::

POST 请求您的集合类型

restaurant集合类型执行POST请求以创建餐厅。

确保您已激活restaurant集合类型的create权限和category集合类型的find权限。

添加?populate=categories 查询参数以返回带有响应的类别。

在此示例中,已创建具有 id:3 的chinese类别。

js
axios
js
import axios from 'axios'

axios
  .post('http://localhost:1337/api/restaurants/?populate=categories', {
    data: {
      name: '宫保鸡丁',
      description:
        '不容错过的中国餐馆。炒菜非常美味',
      categories: [3],
    },
  })
  .then((response) => {
    console.log(response)
  })
Example response
json
{
  "data": {
    "id": 2,
    "attributes": {
      "name": "宫保鸡丁",
      "description": "不容错过的中国餐馆。炒菜非常美味",
      "createdAt": "2022-07-31T09:14:12.569Z",
      "updatedAt": "2022-07-31T09:14:12.569Z",
      "publishedAt": "2022-07-31T09:14:12.566Z",
      "categories": {
        "data": [
          {
            "id": 3,
            "attributes": {
              "name": "chinese",
              "createdAt": "2022-07-31T10:49:03.933Z",
              "updatedAt": "2022-07-31T10:49:04.893Z",
              "publishedAt": "2022-07-31T10:49:04.890Z"
            }
          }
        ]
      }
    }
  },
  "meta": {}
}

Example

./pages/index.js

js
axios
js
import { useState } from 'react'
import axios from 'axios'

function Home({ allCategories, errorCategories }) {
  const [modifiedData, setModifiedData] = useState({
    name: '',
    description: '',
    categories: [],
  })
  const [errorRestaurants, setErrorRestaurants] = useState(null)

  const handleChange = ({ target: { name, value } }) => {
    setModifiedData(prev => ({
      ...prev,
      [name]: value,
    }))
  }

  const handleSubmit = async (e) => {
    e.preventDefault()

    try {
      const response = await axios.post('http://localhost:1337/api/restaurants', {
        data: modifiedData,
      })
      console.log(response)
    }
    catch (error) {
      setErrorRestaurants(error)
    }
  }

  const renderCheckbox = (category) => {
    const { categories } = modifiedData
    const isChecked = categories.includes(category.id)
    const handleCheckboxChange = () => {
      if (!categories.includes(category.id)) {
        handleChange({ target: { name: 'categories', value: categories.concat(category.id) } })
      }
      else {
        handleChange({
          target: { name: 'categories', value: categories.filter(v => v !== category.id) },
        })
      }
    }
    return (
      <div key={category.id}>
        <label htmlFor={category.id}>{category.attributes.Name}</label>
        <input
          type="checkbox"
          checked={isChecked}
          onChange={handleCheckboxChange}
          name="categories"
          id={category.id}
        />
      </div>
    )
  }
  if (errorCategories) {
    return (
      <div>
        An error occured (categories):
        {errorCategories.message}
      </div>
    )
  }
  if (errorRestaurants) {
    return (
      <div>
        An error occured (restaurants):
        {errorRestaurants.message}
      </div>
    )
  }
  return (
    <div>
      <form onSubmit={handleSubmit}>
        <h3>Restaurants</h3>
        <br />
        <label>
          Name:
          <input type="text" name="name" value={modifiedData.name} onChange={handleChange} />
        </label>
        <label>
          Description:
          <input
            type="text"
            name="description"
            value={modifiedData.description}
            onChange={handleChange}
          />
        </label>
        <div>
          <br />
          <b>Select categories</b>
          <br />
          {allCategories.data.map(renderCheckbox)}
        </div>
        <br />
        <button type="submit">Submit</button>
      </form>
    </div>
  )
}

Home.getInitialProps = async (ctx) => {
  try {
    const res = await axios.get('http://localhost:1337/api/categories')
    const allCategories = res.data
    return { allCategories }
  }
  catch (errorCategories) {
    return { errorCategories }
  }
}

export default Home

PUT 请求您的集合类型

restaurant 集合类型执行 PUT 请求,以更新餐厅的类别。

确保您已为 restaurant 集合类型激活 put 权限。

我们认为您的餐厅的 ID 为 2。 您的类别的 ID 为 2

js
axios
js
import axios from 'axios'

axios
  .put('http://localhost:1337/api/restaurants/2/?populate=categories', {
    data: {
      categories: [2],
    },
  })
  .then((response) => {
    console.log(response)
  })
Example response
json
{
  "data": {
    "id": 2,
    "attributes": {
      "name": "Dolemon Sushi",
      "description": "Unmissable chinese Sushi restaurant. The cheese and salmon makis are delicious",
      "createdAt": "2022-07-31T09:14:12.569Z",
      "updatedAt": "2022-07-31T11:17:31.598Z",
      "publishedAt": "2022-07-31T09:14:12.566Z",
      "categories": {
        "data": [
          {
            "id": 2,
            "attributes": {
              "name": "Brunch",
              "createdAt": "2022-07-30T09:23:57.857Z",
              "updatedAt": "2022-07-30T09:26:37.236Z",
              "publishedAt": "2022-07-30T09:26:37.233Z"
            }
          }
        ]
      }
    }
  },
  "meta": {}
}