npm i use-http
url
and options
useFetch
If the last argument of useFetch
is not a dependency array []
, then it will not fire until you call one of the http methods like get
, post
, etc.
import useFetch from 'use-http'
function Todos() {
const [todos, setTodos] = useState([])
const { get, post, response, loading, error } = useFetch('https://example.com')
useEffect(() => { initializeTodos() }, []) // componentDidMount
async function initializeTodos() {
const initialTodos = await get('/todos')
if (response.ok) setTodos(initialTodos)
}
async function addTodo() {
const newTodo = await post('/todos', { title: 'my new todo' })
if (response.ok) setTodos([...todos, newTodo])
}
return (
<>
<button onClick={addTodo}>Add Todo</button>
{error && 'Error!'}
{loading && 'Loading...'}
{todos.map(todo => (
<div key={todo.id}>{todo.title}</div>
))}
</>
)
}
useFetch
This fetch is run onMount/componentDidMount
. The last argument []
means it will run onMount
. If you pass it a variable like [someVariable]
, it will run onMount
and again whenever someVariable
changes values (aka onUpdate
). If no method is specified, GET is the default.
import useFetch from 'use-http'
function Todos() {
const options = {} // these options accept all native `fetch` options
// the last argument below [] means it will fire onMount (GET by default)
const { loading, error, data = [] } = useFetch('https://example.com/todos', options, [])
return (
<>
{error && 'Error!'}
{loading && 'Loading...'}
{data.map(todo => (
<div key={todo.id}>{todo.title}</div>
))}
</>
)
}
Can put suspense
in 2 places. Either useFetch
(A) or Provider
(B).
import useFetch, { Provider } from 'use-http'
function Todos() {
const { data: todos = [] } = useFetch('/todos', {
suspense: true // A. can put `suspense: true` here
}, []) // onMount
return todos.map(todo => <div key={todo.id}>{todo.title}</div>)
}
function App() {
const options = {
suspense: true // B. can put `suspense: true` here too
}
return (
<Provider url='https://example.com' options={options}>
<Suspense fallback='Loading...'>
<Todos />
</Suspense>
</Provider>
)
}
Can put suspense
in 2 places. Either useFetch
(A) or Provider
(B). Suspense mode via managed state is very experimental.
import useFetch, { Provider } from 'use-http'
function Todos() {
const [todos, setTodos] = useState([])
// A. can put `suspense: true` here
const { get, response } = useFetch({ suspense: true })
const loadInitialTodos = async () => {
const todos = await get('/todos')
if (response.ok) setTodos(todos)
}
// componentDidMount
useEffect(() => {
loadInitialTodos()
}, [])
return todos.map(todo => <div key={todo.id}>{todo.title}</div>)
}
function App() {
const options = {
suspense: true // B. can put `suspense: true` here too
}
return (
<Provider url='https://example.com' options={options}>
<Suspense fallback='Loading...'>
<Todos />
</Suspense>
</Provider>
)
}
Consider sponsoring
Ava, Rapid Application Development
Need a freelance software engineer with more than 5 years production experience at companies like Facebook, Discord, Best Buy, and Citrix?
website | email | twitter
Provider
The onNewData
will take the current data, and the newly fetched data, and allow you to merge the two however you choose. In the example below, we are appending the new todos to the end of the current todos.
import useFetch, { Provider } from 'use-http'
const Todos = () => {
const [page, setPage] = useState(1)
const { data = [], loading } = useFetch(`/todos?page=${page}&amountPerPage=15`, {
onNewData: (currTodos, newTodos) => [...currTodos, ...newTodos], // appends newly fetched todos
perPage: 15, // stops making more requests if last todos fetched < 15
}, [page]) // runs onMount AND whenever the `page` updates (onUpdate)
return (
<ul>
{data.map(todo => <li key={todo.id}>{todo.title}</li>}
{loading && 'Loading...'}
{!loading && (
<button onClick={() => setPage(page + 1)}>Load More Todos</button>
)}
</ul>
)
}
const App = () => (
<Provider url='https://example.com'>
<Todos />
</Provider>
)
useFetch
response
object! Details in this video. Technically you can do it, but if you need to access the response.ok
from, for example, within a component's onClick handler, it will be a stale value for ok
where it will be correct for response.ok
. ️️
var [request, response, loading, error] = useFetch('https://example.com')
// want to use object destructuring? You can do that too
var {
request,
response, // �� Do not destructure the `response` object!
loading,
error,
data,
cache, // methods: get, set, has, delete, clear (like `new Map()`)
get,
post,
put,
patch,
delete // don't destructure `delete` though, it's a keyword
del, // <- that's why we have this (del). or use `request.delete`
head,
options,
connect,
trace,
mutate, // GraphQL
query, // GraphQL
abort
} = useFetch('https://example.com')
// �� Do not destructure the `response` object!
// �� This just shows what fields are available in it.
var {
ok,
status,
headers,
data,
type,
statusText,
url,
body,
bodyUsed,
redirected,
// methods
json,
text,
formData,
blob,
arrayBuffer,
clone
} = response
var {
loading,
error,
data,
cache, // methods: get, set, has, delete, clear (like `new Map()`)
get,
post,
put,
patch,
delete // don't destructure `delete` though, it's a keyword
del, // <- that's why we have this (del). or use `request.delete`
mutate, // GraphQL
query, // GraphQL
abort
} = request
useFetch
var request = useFetch('https://example.com')
request.post('/todos', {
no: 'way'
})
useFetch
const { get, abort, loading, data: repos } = useFetch('https://api.github.com/search/repositories?q=')
// the line below is not isomorphic, but for simplicity we're using the browsers `encodeURI`
const searchGithubRepos = e => get(encodeURI(e.target.value))
<>
<input onChange={searchGithubRepos} />
<button onClick={abort}>Abort</button>
{loading ? 'Loading...' : repos.data.items.map(repo => (
<div key={repo.id}>{repo.name}</div>
))}
</>
useFetch
const QUERY = `
query Todos($userID string!) {
todos(userID: $userID) {
id
title
}
}
`
function App() {
const request = useFetch('http://example.com')
const getTodosForUser = id => request.query(QUERY, { userID: id })
return (
<>
<button onClick={() => getTodosForUser('theUsersID')}>Get User's Todos</button>
{request.loading ? 'Loading...' : <pre>{request.data}</pre>}
</>
)
}
useFetch
The Provider
allows us to set a default url
, options
(such as headers) and so on.
const MUTATION = `
mutation CreateTodo($todoTitle string) {
todo(title: $todoTitle) {
id
title
}
}
`
function App() {
const [todoTitle, setTodoTitle] = useState('')
const request = useFetch('http://example.com')
const createtodo = () => request.mutate(MUTATION, { todoTitle })
return (
<>
<input onChange={e => setTodoTitle(e.target.value)} />
<button onClick={createTodo}>Create Todo</button>
{request.loading ? 'Loading...' : <pre>{request.data}</pre>}
</>
)
}
Provider
using the GraphQL useMutation
and useQuery
import { useQuery } from 'use-http'
export default function QueryComponent() {
// can also do it this way:
// const [data, loading, error, query] = useQuery`
// or this way:
// const { data, loading, error, query } = useQuery`
const request = useQuery`
query Todos($userID string!) {
todos(userID: $userID) {
id
title
}
}
`
const getTodosForUser = id => request.query({ userID: id })
return (
<>
<button onClick={() => getTodosForUser('theUsersID')}>Get User's Todos</button>
{request.loading ? 'Loading...' : <pre>{request.data}</pre>}
</>
)
}
import { useMutation } from 'use-http'
export default function MutationComponent() {
const [todoTitle, setTodoTitle] = useState('')
// can also do it this way:
// const request = useMutation`
// or this way:
// const { data, loading, error, mutate } = useMutation`
const [data, loading, error, mutate] = useMutation`
mutation CreateTodo($todoTitle string) {
todo(title: $todoTitle) {
id
title
}
}
`
const createTodo = () => mutate({ todoTitle })
return (
<>
<input onChange={e => setTodoTitle(e.target.value)} />
<button onClick={createTodo}>Create Todo</button>
{loading ? 'Loading...' : <pre>{data}</pre>}
</>
)
}
These props are defaults used in every request inside the <Provider />
. They can be overwritten individually
import { Provider } from 'use-http'
import QueryComponent from './QueryComponent'
import MutationComponent from './MutationComponent'
function App() {
const options = {
headers: {
Authorization: 'Bearer YOUR_TOKEN_HERE'
}
}
return (
<Provider url='http://example.com' options={options}>
<QueryComponent />
<MutationComponent />
<Provider/>
)
}
This example shows how we can do authentication in the request
interceptor and how we can camelCase the results in the response
interceptor
import { Provider } from 'use-http'
import { toCamel } from 'convert-keys'
function App() {
let [token, setToken] = useLocalStorage('token')
const options = {
interceptors: {
// every time we make an http request, this will run 1st before the request is made
// url, path and route are supplied to the interceptor
// request options can be modified and must be returned
request: async ({ options, url, path, route }) => {
if (isExpired(token)) {
token = await getNewToken()
setToken(token)
}
options.headers.Authorization = `Bearer ${token}`
return options
},
// every time we make an http request, before getting the response back, this will run
response: async ({ response, request }) => {
// unfortunately, because this is a JS Response object, we have to modify it directly.
// It shouldn't have any negative affect since this is getting reset on each request.
const res = response
if (res.data) res.data = toCamel(res.data)
return res
}
}
}
return (
<Provider url='http://example.com' options={options}>
<SomeComponent />
<Provider/>
)
}
This example shows how we can upload a file using useFetch
.
import useFetch from 'use-http'
const FileUploader = () => {
const [file, setFile] = useState()
const { post } = useFetch('https://example.com/upload')
const uploadFile = async () => {
const data = new FormData()
data.append('file', file)
if (file instanceof FormData) await post(data)
}
return (
<div>
{/* Drop a file onto the input below */}
<input onChange={e => setFile(e.target.files[0])} />
<button onClick={uploadFile}>Upload</button>
</div>
)
}
This example shows how we can get .json()
, .text()
, .formData()
, .blob()
, .arrayBuffer()
, and all the other http response methods. By default, useFetch
1st tries to call response.json()
under the hood, if that fails it's backup is response.text()
. If that fails, then you need a different response type which is where this comes in.
import useFetch from 'use-http'
const App = () => {
const [name, setName] = useState('')
const { get, loading, error, response } = useFetch('http://example.com')
const handleClick = async () => {
await get('/users/1?name=true') // will return just the user's name
const text = await response.text()
setName(text)
}
return (
<>
<button onClick={handleClick}>Load Data</button>
{error && error.messge}
{loading && "Loading..."}
{name && <div>{name}</div>}
</>
)
}
This example shows how to remove a header all together. Let's say you have <Provider url='url.com' options={{ headers: { Authentication: 'Bearer MY_TOKEN' } }}><App /></Provider>
, but for one api call, you don't want that header in your useFetch
at all for one instance in your app. This would allow you to remove that.
import useFetch from 'use-http'
const Todos = () => {
// let's say for this request, you don't want the `Accept` header at all
const { loading, error, data: todos = [] } = useFetch('/todos', globalOptions => {
delete globalOptions.headers.Accept
return globalOptions
}, []) // onMount
return (
<>
{error && error.messge}
{loading && "Loading..."}
{todos && <ul>{todos.map(todo => <li key={todo.id}>{todo.title}</li>)}</ul>}
</>
)
}
const App = () => {
const options = {
headers: {
Accept: 'application/json'
}
}
return (
<Provider url='https://url.com' options={options}><Todos /></Provider>
}
In this example you can see how retryOn
will retry on a status code of 305
, or if we choose the retryOn()
function, it returns a boolean to decide if we will retry. With retryDelay
we can either have a fixed delay, or a dynamic one by using retryDelay()
. Make sure retries
is set to at minimum 1
otherwise it won't retry the request. If retries > 0
without retryOn
then by default we always retry if there's an error or if !response.ok
. If retryOn: [400]
and retries > 0
then we only retry on a response status of 400
.
import useFetch from 'use-http'
const TestRetry = () => {
const { response, get } = useFetch('https://httpbin.org/status/305', {
// make sure `retries` is set otherwise it won't retry
retries: 1,
retryOn: [305],
// OR
retryOn: async ({ attempt, error, response }) => {
// returns true or false to determine whether to retry
return error || response && response.status >= 300
},
retryDelay: 3000,
// OR
retryDelay: ({ attempt, error, response }) => {
// exponential backoff
return Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)
// linear backoff
return attempt * 1000
}
})
return (
<>
<button onClick={() => get()}>CLICK</button>
<pre>{JSON.stringify(response, null, 2)}</pre>
</>
)
}
Hook | Description |
---|---|
useFetch |
The base hook |
useQuery |
For making a GraphQL query |
useMutation |
For making a GraphQL mutation |
This is exactly what you would pass to the normal js fetch
, with a little extra. All these options can be passed to the <Provider options={/* every option below */} />
, or directly to useFetch
. If you have both in the <Provider />
and in useFetch
, the useFetch
options will overwrite the ones from the <Provider />
Option | Description | Default |
---|---|---|
cacheLife |
After a successful cache update, that cache data will become stale after this duration | 0 |
cachePolicy |
These will be the same ones as Apollo's fetch policies. Possible values are cache-and-network , network-only , cache-only , no-cache , cache-first . Currently only supports cache-first or no-cache |
cache-first |
data |
Allows you to set a default value for data |
undefined |
interceptors.request |
Allows you to do something before an http request is sent out. Useful for authentication if you need to refresh tokens a lot. | undefined |
interceptors.response |
Allows you to do something after an http response is recieved. Useful for something like camelCasing the keys of the response. | undefined |
loading |
Allows you to set default value for loading |
false unless the last argument of useFetch is [] |
onAbort |
Runs when the request is aborted. | empty function |
onError |
Runs when the request get's an error. If retrying, it is only called on the last retry attempt. | empty function |
onNewData |
Merges the current data with the incoming data. Great for pagination. | (curr, new) => new |
onTimeout |
Called when the request times out. | empty function |
persist |
Persists data for the duration of cacheLife . If cacheLife is not set it defaults to 24h. Currently only available in Browser. |
false |
perPage |
Stops making more requests if there is no more data to fetch. (i.e. if we have 25 todos, and the perPage is 10, after fetching 2 times, we will have 20 todos. The last 5 tells us we don't have any more to fetch because it's less than 10) For pagination. | 0 |
responseType |
This will determine how the data field is set. If you put json then it will try to parse it as JSON. If you set it as an array, it will attempt to parse the response in the order of the types you put in the array. Read about why we don't put formData in the defaults in the yellow Note part here. |
['json', 'text', 'blob', 'readableStream'] |
retries |
When a request fails or times out, retry the request this many times. By default it will not retry. | 0 |
retryDelay |
You can retry with certain intervals i.e. 30 seconds 30000 or with custom logic (i.e. to increase retry intervals). |
1000 |
retryOn |
You can retry on certain http status codes or have custom logic to decide whether to retry or not via a function. Make sure retries > 0 otherwise it won't retry. |
[] |
suspense |
Enables Experimental React Suspense mode. example | false |
timeout |
The request will be aborted/cancelled after this amount of time. This is also the interval at which retries will be made at. in milliseconds. If set to 0 , it will not timeout except for browser defaults. |
0 |
const options = {
// accepts all `fetch` options such as headers, method, etc.
// The time in milliseconds that cache data remains fresh.
cacheLife: 0,
// Cache responses to improve speed and reduce amount of requests
// Only one request to the same endpoint will be initiated unless cacheLife expires for 'cache-first'.
cachePolicy: 'cache-first', // 'no-cache'
// set's the default for the `data` field
data: [],
// typically, `interceptors` would be added as an option to the `<Provider />`
interceptors: {
request: async ({ options, url, path, route }) => { // `async` is not required
return options // returning the `options` is important
},
response: async ({ response, request }) => {
// notes:
// - `response.data` is equivalent to `await response.json()`
// - `request` is an object matching the standard fetch's options
return response // returning the `response` is important
}
},
// set's the default for `loading` field
loading: false,
// called when aborting the request
onAbort: () => {},
// runs when an error happens.
onError: ({ error }) => {},
// this will allow you to merge the `data` for pagination.
onNewData: (currData, newData) => {
return [...currData, ...newData]
},
// called when the request times out
onTimeout: () => {},
// this will tell useFetch not to run the request if the list doesn't haveMore. (pagination)
// i.e. if the last page fetched was < 15, don't run the request again
perPage: 15,
// Allows caching to persist after page refresh. Only supported in the Browser currently.
persist: false,
// this would basically call `await response.json()`
// and set the `data` and `response.data` field to the output
responseType: 'json',
// OR can be an array. It's an array by default.
// We will try to get the `data` by attempting to extract
// it via these body interface methods, one by one in
// this order. We skip `formData` because it's mostly used
// for service workers.
responseType: ['json', 'text', 'blob', 'arrayBuffer'],
// amount of times it should retry before erroring out
retries: 3,
// The time between retries
retryDelay: 10000,
// OR
// Can be a function which is used if we want change the time in between each retry
retryDelay({ attempt, error, response }) {
// exponential backoff
return Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)
// linear backoff
return attempt * 1000
},
// make sure `retries` is set otherwise it won't retry
// can retry on certain http status codes
retryOn: [503],
// OR
async retryOn({ attempt, error, response }) {
// retry on any network error, or 4xx or 5xx status codes
if (error !== null || response.status >= 400) {
console.log(`retrying, attempt number ${attempt + 1}`);
return true;
}
},
// enables experimental React Suspense mode
suspense: true, // defaults to `false`
// amount of time before the request get's canceled/aborted
timeout: 10000,
}
useFetch(options)
// OR
<Provider options={options}><ResOfYourApp /></Provider>
Does your company use use-http? Consider sponsoring the project to fund new features, bug fixes, and more.
If you need support for IE, you will need to add additional polyfills. The React docs suggest these polyfills, but from this issue we have found it to work fine with the react-app-polyfill
. If you have any updates to this browser list, please submit a PR!
Edge |
Firefox |
Chrome |
Safari |
Opera |
---|---|---|---|---|
12+ | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
If you have feature requests, submit an issue to let us know what you would like to see!
prefetching
global cache state management
optimistic updates
persist
support for React Native
better loading state management. When using only 1 useFetch in a component and we usePromise.all([get('/todos/1'), get('/todos/2')])
then don't have a loading true,loading false on each request. Just have loading true on 1st request, and loading falseon last request.
is making a gitpod useful here?
suspense
<Suspense />
component.
.read()
to request
suspense: true
optionmaybe add translations like this one
maybe add contributors all-contributors
add sponsors similar to this
Error handling
response.json()
and there is no response yettests
useMutation
+ useQuery
response
see this PRresponse.formData()
and some of the other http response methods
work properlyonMount
works properly with all variants of passing useEffect(fn, [request.get])
and not causing an infinite loopasync
tests for interceptors.response
retryDelay
and timeout
are both set. It works, but is annoying to deal with timers in tests. resourcetimeout
with retries > 0
. (also do retires > 1
) Need to figure out how to advance timers properly to write this and the test above take a look at how react-apollo-hooks work. Maybe ad useSubscription
and const request = useFetch(); request.subscribe()
or something along those lines
make this a github package
Documentation:
potential option ideas
const request = useFetch({
graphql: {
// all options can also be put in here
// to overwrite those of `useFetch` for
// `useMutation` and `useQuery`
},
// by default this is true, but if set to false
// then we default to the responseType array of trying 'json' first, then 'text', etc.
// hopefully I get some answers on here: https://bit.ly/3afPlJS
responseTypeGuessing: true,
// Allows you to pass in your own cache to useFetch
// This is controversial though because `cache` is an option in the requestInit
// and it's value is a string. See: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache
// One possible solution is to move the default `fetch`'s `cache` to `cachePolicy`.
// I don't really like this solution though.
// Another solution is to only allow the `cache` option with the `<Provider cache={new Map()} />`
cache: new Map(),
// these will be the exact same ones as Apollo's
cachePolicy: 'cache-and-network', 'network-only', 'cache-only', 'no-cache' // 'cache-first'
// potential idea to fetch on server instead of just having `loading` state. Not sure if this is a good idea though
onServer: true,
onSuccess: (/* idk what to put here */) => {},
// if you would prefer to pass the query in the config
query: `some graphql query`
// if you would prefer to pass the mutation in the config
mutation: `some graphql mutation`
refreshWhenHidden: false,
})
// potential for causing a rerender after clearing cache if needed
request.cache.clear(true)
potential option ideas for GraphQL
const request = useQuery({ onMount: true })`your graphql query`
const request = useFetch(...)
const userID = 'some-user-uuid'
const res = await request.query({ userID })`
query Todos($userID string!) {
todos(userID: $userID) {
id
title
}
}
`
make code editor plugin/package/extension that adds GraphQL syntax highlighting for useQuery
and useMutation
add React Native test suite
前言 最近开始学习React,跟着Kent学,有很多干货,这里分享React Hook中的useCallback 代码分享到了codesandbox,App.js是最后的最佳实践,中间代码放在了archive文件夹上了 一、background 正常来说,当处理sideEffect的时候,useEffect的第二个参数会传一个dependence list,只有当list中地参数变化时候,这个ef
[WebMethod] public bool IsUserExist(string userName) { if (userName == "raymond") return true; else return false; } protected void Button2_Click(object sender, EventArgs e) { byte[] data = System.Text
问题描述 使用Vue3+vite3+TS构建项目后,使用yarn serve或者 npm run dev命令启动项目后,显示“Network: use --host to expose”,页面无法访问,yarn启动和npm启动显示如下所示: yarn run v1.22.19 $ vite preview ➜ Local: http://127.0.0.1:4173/ ➜ Netw
前言 centos 7 源码编译安装ffmpeg 错误 编译FFMPEG时,出现了错误 nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.。 原因 这是因为 FFMPEG为了提高编译速度,使用了汇编指令,如MMX和SSE等。如果系统中没有yasm指令的话,就会该错误。 解决办法 安装yasm。 安装y
在编译ffmpeg时,执行./configure,报出了如下错误 nasm/yasm not found or too old. Use –disable-x86asm for a crippled build. 后在网上找到了解决方法: 1.在http://www.tortall.net/projects/yasm/releases/上下载适合自己的版本 2.解压并进入yasm的目录 3.执行.
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 起因 问题重现 问题原因 解决方法 1. 修改 vite.config.js 配置 2.通过 Vite CLI 配置 3. 修改 npm 脚本 起因 当使用 Vite 构建项目后,需要通过局域网中的电脑或手机访问服务调试时,发现通过 IP + 端口无法访问。 问题重现 当运行 npm run dev | serve 命令时
安装ffmpeg过程中,执行./configure时,报yasm/nasm not found or too old. Use --disable-yasm for a crippledbuild错误,分析、解决如下: 分析:yasm是汇编编译器,ffmpeg为了提高效率使用了汇编指令,如MMX和SSE等。所以系统中未安装yasm时,就会报上面错误。 解决:安装yasm编译器。安装方法如下: 在h
manual: http://tuckey.org/urlrewrite/manual/4.0/ 1. If you want to take into account the url query parameters to the filter rules add use-query-string="true" to <urlrewrite use-query-string="true"
版权归Aaidong所有〜转载需声名〜 欢迎大家访问:http://blog.csdn.net/aaidong clang: error: linker command failed with exit code 1 (use -v to see invocation) 的Xcode错误调试,在iOS开发中算是一个最常见的错误。但是出现这个错误的情况却有好多种,以下总结希望可以对大家有点帮助。
yum repolist “Loaded plugins: fastestmirror, product-id, search-disabled-repos, subscription-manager This system is not registered with an entitlement server. You can use subscription-manager to regis
问题来源: UDT的android平台移植过程中,在用NDK编译buffer.cpp文件时出现error: exception handling disabled, use -fexceptions to enable。 问题解决: 此问题的出现是编译器的异常异常捕获被禁用了,需要在Android.mk文件中开启。在Android.mk文件中添加:LOCAL_CPPFLAGS += -fex
发布IOS遇到了/clang:-1: linker command failed with exit code 1 (use -v to see invocation)问题 相关链接: https://www.jianshu.com/p/03aec7c4867d http://www.cnblogs.com/xsyl/p/6085844.html 最后解决方案 1. ”Build Settin
微信小程序使用background-image没有图片显示 报错信息:图片-do-not-use-local-path pages/index/index.wxss 中的本地资源图片无法通过 WXSS 获取 解决方法:可以使用网络图片,或者 base64,或者使用标签。 .container { display: flex; background-repeat:no-repeat;
描述 (Description) 此函数将MODULE导出的所有函数或仅LIST引用的函数导入当前包的名称空间。 有效地相当于 - BEGIN { require "Module.pm"; Module->import(); } 也用于在当前脚本上强加编译器指令(pragma),尽管这些只是模块。 请注意,在编译时会评估use语句。 在执行时评估require语句。 如果Module和LIST之
主要内容:语法,示例如果您的系统中有多个数据库,那么在开始操作之前,您需要先选择一个数据库。 SQL USE 语句用来选择一个已经存在的数据库。 语法 USE 语句的基本语法如下: USE DatabaseName; DatabaseName 表示要选择的数据库名称,它必须是存在的。 示例 首先使用 SHOW DATABASES 语句查看所有已存在的数据库: 现在,如果您想使用 test 数据库,则可以执行下面的 S
WinSCP can be downloaded in the form of standalone Portable executables. The executables in the Portable executables package are identical to the executables in an Installation package. The difference
一般来讲,SRS的应用方式有以下几类: 搭建大规模CDN集群,可以在CDN内部的源站和边缘部署SRS。 小型业务快速搭建几台流媒体集群,譬如学校、企业等,需要分发的流不多,同时CDN覆盖不如自己部署几个节点,可以用SRS搭建自己的小集群。 SRS作为源站,CDN作为加速边缘集群。比如推流到CDN后CDN转推到源站,播放时CDN会从源站取流。这样可以同时使用多个CDN。同时还可以在源站做DRM和DV
基础配置 自定义欢迎页面 ITEM NOTE 目的 验证自定制默认欢迎页面 步骤 访问默认欢迎页面(http://192.168.100.71/) 自定义欢迎页面 echo "Hello Nginx" > /usr/share/nginx/html/index.html 自定义测试界面 echo "ok" > /usr/share/nginx/html/hello 结果 访问默认欢迎页面 $ cu
useClippy useClippy is a TypeScript-friendly React hook for reading from and writing tothe user's clipboard. Not to be confused with Microsoft Office's assistant, Clippy. �� Demo You can seeuse-clippy