最近文章

React Apollo入门

入门Apollo Client最简单的方法是使用Apollo Boost,它会给客户端配置推荐的设置。使用Apollo Boost创建app的内容包括缓存,本地状态管理以及错误处理。安装首先安装以下的软件包:npm install apollo-boost react-apollo graphql-tag graphq
标签:

React 18 createRoot方法:ReactDOM.render is no longer supported in React 18

自React 18开始,ReactDOM.render被废弃,使用React 18会以兼容模式运行旧代码,并且会有类似以下的警告:Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will beh
标签:

自定义React Hooks(记录先前状态):usePrevious

usePrevious Hoos可以用来存储props或以前的状态。 首先,创建一个接受值的Hook。 然后,我们使用useRef Hook为该值创建一个ref。 最后,使用useEffect记住最新值。代码示例:const usePrevious = value => { const ref = React.useEffect(); React.u
标签:

自定义React Hooks(超时):useTimeout

使用useTimeout Hook,我们可以使用声明式方法来实现setTimeout。 创建一个带有回调callback和延迟的Hook。 使用useRef为callback创建一个ref。两次使用useEffect。 一次用于记住最后一个回调,一次用于设置超时和清除。示例:const useTimeout = (callback, delay) => { cons
标签:

IDEA启动tomcat,日志中文字符有乱码“淇℃伅”

新安装了IDEA,集成Tomcat。启动时,日志的中文变成了乱码:15-Mar-2020 11:15:56.143 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.鏈嶅姟鍣ㄧ増鏈�: Apache Tomcat/9.0.2215-Mar-2020 11:15:56.148 淇℃伅 [mai
标签:

解决React错误:TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined

运行React应用:yarn start报错:TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined在stackoverflow上找到了解决方法,只需要把react-scripts升级到"^3.4.0"即可。解决步骤:在package.json中,把"
标签:

IntelliJ IDEA Community社区版集成添加Tomcat插件(Smart Tomcat)

IntelliJ IDEA Community社区版是一个简版,是没有集成Tomcat的。我们可以通过插件的方式把tomcat的环境集成到IDEA社区版中,其中插件可以是smart tomcat。一、进入插件管理界面File -> Settings -> Plugins 二、在插件界面的搜索框里输入“Tomcat”,选择Smart Tomcat 安装。安装成
标签:

React Apollo入门

入门Apollo Client最简单的方法是使用Apollo Boost,它会给客户端配置推荐的设置。使用Apollo Boost创建app的内容包括缓存,本地状态管理以及错误处理。

安装

首先安装以下的软件包:

npm install apollo-boost react-apollo graphql-tag graphql --save
  • apollo-boost:这个包包含了搭建Apollo客户端需要的所有东西。
  • react-apollo:集成React的视图层
  • graphql-tag:解析GraphQL 查询必要依赖
  • graphql:用于解析GraphQL 查询

示例准备

客户端:如果没有React app,可以使用create-react-app来创建一个React app。或者使用CodeSandbox来创建一个React沙盒。

GraphQL服务端:可以使用Launchpad来作为GraphQL的演示服务端

创建客户端

创建Apollo客户端,它用于与GraphQL服务器交互。ApolloClient只需要一个参数,GraphQL服务器的endpoint。

在index.js实例化ApolloClient

import ApolloClient from "apollo-boost";

const client = new ApolloClient({
  uri"https://w5xlvm3vzz.lp.gql.zone/graphql"
});

到此我们就可以使用ApolloClient实例化的客户端来获取数据,在index.js添加如下代码:

import gql from "graphql-tag";

client
  .query({
    query: gql`
      {
        rates(currency: "USD") {
          currency
        }
      }
    `
  })
  .then(({ data }) => console.log({ data }));

查询数据需要导入gql,使用client.query()执行查询。

集成客户端到React

现在把上面的新建的apollo客户端集成到React应用里。react-apollo提供ApolloProvider组件,ApolloProvider类似于React的context provider。它会把apollo客户端放入到React app的上下文里,在组件树的任何地方都是可以获取到apollo客户端。

在index.js,集成ApolloProvider到React app:

import React from "react";
import { render } from "react-dom";

import { ApolloProvider } from "react-apollo";

const App = () => (
  <ApolloProvider client={client}>
    <div>
      <h2>Apollo App demo</h2>
    </div>
  </ApolloProvider>
);

render(<App />document.getElementById("root"));

请求数据

集成ApolloProvider到React app后,就可以向GraphQL服务器请求数据。react-apollo提供了一个Query React组件。Query组件是使用render prop pattern来向React UI传递GraphQL数据。

示例:

import { Query } from "react-apollo";
import gql from "graphql-tag";

const ExchangeRates = () => (
  <Query
    query={gql`
      {
        rates(currency: "USD") {
          currency
          rate
        }
      }
    `}
  >
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;

      return data.rates.map(({ currency, rate }) => (
        <div key={currency}>
          <p>{`${currency}: ${rate}`}</p>
        </div>
      ));
    }}
  </Query>
);

Query组件的query属性的值为gql函数,它是graphql查询语句。

Query组件的子节点也是一个函数,它用来决定怎么渲染graphql返回的数据到UI。这个函数有三个参数:loading,error,data。当graphql返回数据后,会传给data参数用来渲染UI。

到此就集成Apollo Client到React app了。

参考:https://www.apollographql.com/docs/react/essentials/get-started.html#API

React 18 createRoot方法:ReactDOM.render is no longer supported in React 18

自React 18开始,ReactDOM.render被废弃,使用React 18会以兼容模式运行旧代码,并且会有类似以下的警告:

Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

使用createRoot

原来渲染方式:

import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);

使用createRoot后:

import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App tab="home" />);

首先通过createRoot创建root对象,createRoot的参数是应用挂载的Element元素。接着调用root对象的render方法渲染。

index.js的变化

原来方式:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

使用createRoot后:

import React from 'react';

import './index.css';
import App from './App';
import { createRoot } from 'react-dom/client';

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<React.StrictMode>
  <App />
</React.StrictMode>);

自定义React Hooks(记录先前状态):usePrevious

usePrevious Hoos可以用来存储props或以前的状态。

  1.  首先,创建一个接受值的Hook。
  2.  然后,我们使用useRef Hook为该值创建一个ref。
  3.  最后,使用useEffect记住最新值。

代码示例:

const usePrevious = value => {
const ref = React.useEffect();
React.useEffect(()=> {
ref.current = value;
});
return ref.current;
}

使用示例:

const MoneyCount = () => {
const [value, setValue] = React.useState(0);
const lastValue = usePrevious(value);
return (
<div>
<p>Current: {value} - Previous:{lastValue}</p>
<button onClick={()=>setValue(value+1)}> Increment Money</button>
</div>
);
};
ReactDOM.render(<MoneyCount />, document.getElementById("root"));

自定义React Hooks(超时):useTimeout

使用useTimeout Hook,我们可以使用声明式方法来实现setTimeout。 

  1. 创建一个带有回调callback和延迟的Hook。 
  2. 使用useRef为callback创建一个ref。
  3. 两次使用useEffect。 一次用于记住最后一个回调,一次用于设置超时和清除。

示例:

const useTimeout = (callback, delay) => {
const savedCallback = React.useRef();
React.useEffect(() => {
function tick() {
savedCallback.current();
}
if(delay != null) {
let id = setTimeout(tick, delay);
return () => clearTimeout(id);
}
},[delay])
}

使用示例:

const ExampleTimerFiveSeconds = props => {
const [seconds, setSeconds] = React.useState(0);
useTimeout(() => {
setSeconds(seconds+1);
}, 5000);
return <p>{seconds}</p>
}
ReactDOM.render(<ExampleTimerFiveSeconds />, document.getElementById("root"));

IDEA启动tomcat,日志中文字符有乱码“淇℃伅”

新安装了IDEA,集成Tomcat。启动时,日志的中文变成了乱码:

15-Mar-2020 11:15:56.143 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.鏈嶅姟鍣ㄧ増鏈�:        Apache Tomcat/9.0.22
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.鏋勫缓: Jul 4 2019 14:20:06 UTC
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.22.0
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Windows 10
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log OS.鐗堟湰: 10.0
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log 缁�.閫�: amd64
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log Java 鐜鍙橀噺: C:\Program Files\Java\jdk1.8.0_202\jre
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM 鐗堟湰: 1.8.0_202-b08
15-Mar-2020 11:15:56.148 淇℃伅 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM.渚涘簲鍟�: Oracle Corporation

找了很多方案,把所有IDEA的相关编码设置为UTF-8,在jvm启动假如参数-Dfile.encoding=UTF-8也不行。

后来发现这个日志输出属于tomcat,所以在tomcat的配置里找到了解决方案。

打开tomcat安装目录下的conf/logging.properties,找到:

java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
java.util.logging.ConsoleHandler.encoding = UTF-8

把java.util.logging.ConsoleHandler.encoding改为GBK,

java.util.logging.ConsoleHandler.encoding = GBK

保存,重新启动tomcat,日志显示成功:

15-Mar-2020 11:22:51.841 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.服务器版本:        Apache Tomcat/9.0.22
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server.构建: Jul 4 2019 14:20:06 UTC
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.22.0
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Windows 10
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log OS.版本: 10.0
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log 结.造: amd64
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java 环境变量: C:\Program Files\Java\jdk1.8.0_202\jre
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM 版本: 1.8.0_202-b08
15-Mar-2020 11:22:51.843 信息 [main] org.apache.catalina.startup.VersionLoggerListener.log JVM.供应商: Oracle Corporation

解决React错误:TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined

运行React应用:

yarn start

报错:

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined

在stackoverflow上找到了解决方法,只需要把react-scripts升级到"^3.4.0"即可。

解决步骤:

  1. 在package.json中,把"react-scripts": "^3.x.x" 替换为"react-scripts": "^3.4.0"
  2. 删除node_modules文件夹
  3. 执行npm install 或者 yarn install重新安装依赖包

IntelliJ IDEA Community社区版集成添加Tomcat插件(Smart Tomcat)

IntelliJ IDEA Community社区版是一个简版,是没有集成Tomcat的。我们可以通过插件的方式把tomcat的环境集成到IDEA社区版中,其中插件可以是smart tomcat。

一、进入插件管理界面

File -> Settings -> Plugins


二、在插件界面的搜索框里输入“Tomcat”,选择Smart Tomcat 安装。安装成功后,按钮会变成绿色“Restart IDEA”,重启IDEA。

三、添加tomcat配置

1、在顶部菜单 Run -> Edit Configurations 进入设置运行配置界面

2、选择配置界面左上角的加号,就可以看到smart tomcat的添加插件,选择插件添加新配置。

四、配置tomcat

新建完tomcat的配置后,需要对tomcat做以下配置:

1、项目名称

2、deployment:部署地址,注意此处需要填写的路径是源码里webapp的路径。

3、Context Path: 发布的上下文,即访问url的前面的根路径(会自动识别,一般不需要修改)

4、tomcat访问相关的端口

5、启动tomcat虚拟机的相关参数,如设置虚拟机的内存空间等等(开发一般不需要设置)

如图:

五、启动tomcat

配置完tomcat后,就可以在界面的右上角看到用于运行tomcat的图标。