若水微香

文章 评论 浏览 27

若水微香 2025-02-20 14:52:04

只需在属性上使用linq

x.Properties.Where(j => j.Type == JTokenType.Null)

Just use LINQ on the Properties

x.Properties.Where(j => j.Type == JTokenType.Null)

C#如何在动态对象中获取nth对象属性名称

若水微香 2025-02-20 13:12:40

使用SwaggerHub和OpenAPI 2规格,这就是我将此文件上传工作的方式。让我知道您是否有任何疑问。这是用YAML而不是JSON规格编写的。它花了一些阅读和一些实验,但这是GCLOUD文档: htttps:htttps:// cloud。 google.com/storage/docs/uploading-objects
以及SwaggerHub信息:

  /upload/storage/v1/b/{bucket}/o?uploadType=media&name={objectName}:
    post:
      summary: Upload an object directly to a bucket
      description: Upload an object directly to a bucket
      consumes:
        - multipart/form-data
      produces:
        - application/json
      parameters:
        - in: header
          name: Authorization
          type: string
          required: true
        - in: path
          name: bucket
          required: true
          type: string
          description: The name of the bucket to upload to.
        - in: path
          name: objectName
          required: true
          type: string
          description: The name the object will receive in the bucket.
        - in: header
          name: Content-Type
          type: string
          required: true
          description: The content type of the upload. Ex. text/plain
        - in: formData
          name: fileToUpload
          type: file
          description: The file to upload.
      responses:
        200:
          description: OK
        204:
          description: Success - No Content
        400:
          description: Bad Request
        401:
          description: Insufficient Privileges
        404:
          description: Not Found

它确实接受类型:formdata请求中的文件。

With SwaggerHub and OpenAPI 2 spec, this is how I got this file upload to work. Let me know if you have any questions. This is written in YAML as opposed to JSON spec. It took some reading and some experimentation, but here's the Gcloud documentation: https://cloud.google.com/storage/docs/uploading-objects
And the SwaggerHub info as well: https://swagger.io/docs/specification/2-0/file-upload/

  /upload/storage/v1/b/{bucket}/o?uploadType=media&name={objectName}:
    post:
      summary: Upload an object directly to a bucket
      description: Upload an object directly to a bucket
      consumes:
        - multipart/form-data
      produces:
        - application/json
      parameters:
        - in: header
          name: Authorization
          type: string
          required: true
        - in: path
          name: bucket
          required: true
          type: string
          description: The name of the bucket to upload to.
        - in: path
          name: objectName
          required: true
          type: string
          description: The name the object will receive in the bucket.
        - in: header
          name: Content-Type
          type: string
          required: true
          description: The content type of the upload. Ex. text/plain
        - in: formData
          name: fileToUpload
          type: file
          description: The file to upload.
      responses:
        200:
          description: OK
        204:
          description: Success - No Content
        400:
          description: Bad Request
        401:
          description: Insufficient Privileges
        404:
          description: Not Found

It DOES accept type: file in the formData request.

在GCP API网关中上传文件

若水微香 2025-02-19 14:00:03

,它使用配置(例如)将typecript转换为javaScript,捆绑sass,少文件,捆绑svg文件等

首先, webpack是一种构建工具 是一种反应样板,在引擎盖下使用 babel和webpack,已经为最常见的方案提供了配置,因此您不必担心 它。

从您的问题中不清楚,初始化的意思是什么。我只能假设您的意思是用中等简单的学习曲线引导应用程序。如果是这种情况,CRA是必经之路。

First, Webpack is a build tool, which uses configuration to (as an example) transpile Typescript to JavaScript, bundle SASS, LESS files, bundle SVG files etc.

Create React App is a React boilerplate that uses Babel and Webpack under the hood, with configurations already in place for the most common scenarios, so you don't have to worry about it.

It is not clear from your question, what initialization means. I can only assume that you mean to bootstrap an application with a moderately easy learning curve. If that is the case, CRA is the way to go.

我应该使用webpack还是创建反应应用?

若水微香 2025-02-19 09:56:17

在您的代码中, total_encontrado 2 ,它大于或等于 1 。结果,您给出 #select 的条件始终是正确的,因此它选择了每个字符的索引。然后,您将其映射到索引。

相反,您可能只想选择匹配 letra_procurada 的字母。

palavra_secreta = "programador"
letra_procurada = "a"
total_encontrado = palavra_secreta.count letra_procurada

palavra_secreta_array = palavra_secreta.split("")
puts palavra_secreta_array
     .each_with_index
     .select { |letra, index| letra_procurada == letra }
     .map { |pair| pair[1] }

您也可以使用 #FILTER_MAP (Ruby 2.7及以后)来简化这一点。

palavra_secreta = "programador"
letra_procurada = "a"
total_encontrado = palavra_secreta.count letra_procurada

palavra_secreta_array = palavra_secreta.split("")
puts palavra_secreta_array
     .each_with_index
     .filter_map { |letra, index| index if letra_procurada == letra }

In your code, total_encontrado is 2, which is greater than or equal to 1. As a result, the condition you give to #select is always true, so it selects every character with its index. You then map that to just the indices.

Instead, you likely want to select only the letters that match letra_procurada.

palavra_secreta = "programador"
letra_procurada = "a"
total_encontrado = palavra_secreta.count letra_procurada

palavra_secreta_array = palavra_secreta.split("")
puts palavra_secreta_array
     .each_with_index
     .select { |letra, index| letra_procurada == letra }
     .map { |pair| pair[1] }

You could also use #filter_map (Ruby 2.7 and later) to simplify this.

palavra_secreta = "programador"
letra_procurada = "a"
total_encontrado = palavra_secreta.count letra_procurada

palavra_secreta_array = palavra_secreta.split("")
puts palavra_secreta_array
     .each_with_index
     .filter_map { |letra, index| index if letra_procurada == letra }

多个索引阵列 - 红宝石

若水微香 2025-02-19 05:48:13

同样重要的是要记住,听众必须收听所有主节点的通知。

请参阅: https://github.com/spring-projects/springs/springs/springs/spring -DATA-REDIS/eskity/1782

添加生菜属性以与群集解决问题联系。我的配置:

  data:
    redis:
      password: your-password
      ssl:
        enabled: true
      cluster:
        nodes: node-address
      lettuce:
        cluster:
          refresh:
            dynamic-refresh-sources: false
            period: PT1S
        pool:
          max-active: 15
          max-wait: -1
          max-idle: -1
          min-idle: 5 

It is also important to remember that the listener must listen notifications from all master nodes.

Please see: https://github.com/spring-projects/spring-data-redis/issues/1782

Adding lettuce properties to connect with cluster solves problem. My config:

  data:
    redis:
      password: your-password
      ssl:
        enabled: true
      cluster:
        nodes: node-address
      lettuce:
        cluster:
          refresh:
            dynamic-refresh-sources: false
            period: PT1S
        pool:
          max-active: 15
          max-wait: -1
          max-idle: -1
          min-idle: 5 

如何使用GCP托管群集使用Spring Data Redis收听Keyspace事件?

若水微香 2025-02-18 18:27:35

我不确定您在这里问什么...为什么代码不起作用?

说明:

首先,我很确定至少 的一部分 time timer()的输出 strings 您都将其连接在一起,然后试图以数字为单位

当您进行时间 + Time()时,它与“ 12:48:39” + Timer()相同,例如,如果计时器的输出为0:01 :12(秒= 72),那与做:

"12:48:39" + "0:01:12"

它只会输出“ 12:48:390:01:12” ,因为它将加成两个字符串。

当您将其传递到 parseint()中时,您本质上是在做:

parseInt("12:48:390:01:12")

parseint()不知道该怎么办,因为它不是简单的数字,所以它只会解析起点并扔掉其余的;它将返回 12 ,第一个数字。

解决方案:

因此...如果您的目标是添加两次,我建议使用 date ,它允许您正确存储日期和时间。请参阅:在javascript中添加两个日期

希望这会有所帮助

I'm not really sure what you're asking here... why the code isn't working?

Explanation:

First of all I'm pretty sure at least part of the issue is the fact that time and the output of timer() are both strings which you are concatenating together and then attempting to parse as numbers.

When you do time + timer() it's the same as doing "12:48:39" + timer() and for example if the output of timer is 0:01:12 (seconds = 72) then that's the same as doing:

"12:48:39" + "0:01:12"

Which will just output "12:48:390:01:12" because it will concatenate the two strings.

When you then pass that into parseInt(), you are essentially doing:

parseInt("12:48:390:01:12")

parseInt() won't know what to do with that since it's not simple number so it will just parse the beginning and throw away the rest; it will return 12, the first number.

Solution:

So... if your goal is to add two times I recommend using Date which allows you to store dates and times properly. See: Add two dates times together in javascript

Hope this helps :)

JavaScript时间。将1添加到当前时间

若水微香 2025-02-18 09:37:07

我最近一直在处理很多序列化,并在处理值类型的无数据数据时发现了以下文章和帖子。

如何使c#中的xmlSerializer在c# - serialization 中详细介绍XMLSerialializer的漂亮技巧。具体而言,XMLSerialier寻找XXXSPEFIFIED BOOLEAN属性以确定是否应包括在内,这使您可以忽略nulls。

亚历克斯·斯科德利(Alex Scordellis)问了一个stackoverflow问题,该问题收到一个很好的答案。亚历克斯还在他的博客上做了很好的文章,他试图解决 使用XmlSerializer将其验证为无效的< int>

I've been messing around with serialization a lot myself of late and have found the following articles and posts helpful when dealing with null data for value types.

The answer to How to make a value type nullable with XmlSerializer in C# - serialization details a pretty nifty trick of the XmlSerializer. Specifically, the XmlSerialier looks for a XXXSpecified boolean property to determine if it should be included which allows you to ignore nulls.

Alex Scordellis asked a StackOverflow question which received a good answer. Alex also did a good writeup on his blog about the problem he was trying to solve Using XmlSerializer to deserialize into a Nullable<int>.

The MSDN documentation on Xsi:nil Attribute Binding Support is also useful. As is the documentation on IXmlSerializable Interface, though writing your own implementation should be your last resort.

使用XMLSerializer的deperialization空XML属性值

若水微香 2025-02-18 08:16:41

问题在于 enfort jasmine package.json的属性:

Jasmine仅导出 Jasmine.js file,

"exports": "./lib/jasmine.js"

但在中Jasmine-ts 代码需要命令文件(围绕第164行),

const Command = require("jasmine/lib/command");

现在此文件不是导出的一部分,因此它会引发错误:

错误:软件包subpath'./lib/command'未通过“ exports”定义

来修复此茉莉花需要导出 jasmine-ts 使用的命令文件。
我在茉莉 package.json 中测试了以下更改,并解决了问题:

"exports": {
  ".": "./lib/jasmine.js",
  "./lib/command": "./lib/command.js"
}

更改Jasmine package.json 不是一个很好的解决方案,但目前这是唯一的解决方案我的头顶。
我将尝试向茉莉花GitHub存储库打开问题。

The problem is in the in the exports property of jasmine package.json:

Jasmine exports only the jasmine.js file

"exports": "./lib/jasmine.js"

But in the jasmine-ts code there is a require to command file (around row 164)

const Command = require("jasmine/lib/command");

Now this file is not part of the exports so it throws the error:

Error: Package subpath './lib/command' is not defined by "exports"

To fix this jasmine need to export also the command file used by jasmine-ts.
I tested with the following changes in jasmine package.json and solve the problem:

"exports": {
  ".": "./lib/jasmine.js",
  "./lib/command": "./lib/command.js"
}

Changing the jasmine package.json is not a great solution but for now this is the only solution on top of my mind.
I'll try open an issue to jasmine github repository.

如何求解“错误:软件包子路口..&quot;使用茉莉花-TS?

若水微香 2025-02-17 08:40:44

尝试以下代码:

import smtplib
from email.utils import formataddr
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText


msg = MIMEMultipart()
body_part = MIMEText('Write you text here.')
user = '[email protected]'
password = 'xxxx'
msg['Subject'] = 'You subject'
msg['From'] = formataddr(('yyyyy', '[email protected]'))
msg['To'] = '[email protected]'
msg.attach(body_part)
smtp_obj = smtplib.SMTP_SSL("smtp.gmail.com", 465)
smtp_obj.login(user, password)
smtp_obj.sendmail(msg['From'], msg['To'], msg.as_string())
smtp_obj.quit()

更新:如何将文件附加到电子邮件:

只需将以下行添加到上面的脚本中即可。

from email.mime.application import MIMEApplication
path = './../' #The path of your file.

with open(path + filename,'rb') as file:    
        msg.attach(MIMEApplication(file.read(), Name='filename'))

Try the following code:

import smtplib
from email.utils import formataddr
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText


msg = MIMEMultipart()
body_part = MIMEText('Write you text here.')
user = '[email protected]'
password = 'xxxx'
msg['Subject'] = 'You subject'
msg['From'] = formataddr(('yyyyy', '[email protected]'))
msg['To'] = '[email protected]'
msg.attach(body_part)
smtp_obj = smtplib.SMTP_SSL("smtp.gmail.com", 465)
smtp_obj.login(user, password)
smtp_obj.sendmail(msg['From'], msg['To'], msg.as_string())
smtp_obj.quit()

Update: How to attach a file to your email:

Just add the following lines to the script above.

from email.mime.application import MIMEApplication
path = './../' #The path of your file.

with open(path + filename,'rb') as file:    
        msg.attach(MIMEApplication(file.read(), Name='filename'))

接收-SMTP实例没有属性错误

若水微香 2025-02-17 05:25:04

您的USERCONTROL没有BO类实例。您只需在SerialPortinItControl中定义BO类,因此,当您创建它的Instanse时,它将是这样的:

var instBO = new SerialPortInitControl.BO.BO_GetValues()

因此,您创建了BO类的对象,但是当您将其存储在UserConrol中时?

public partial class SerialPortInitControl : UserControl
{
    public class BO
    {
        public class BO_GetValues
        {
            public string name;
            public string baudRate;
            public string paritie;
            public string dataBits;
            public string stopBits;
        }
    }

    //instance of BO class
    public BO BO_Instanse {get;}
    
    //instance of BO.Get_Values class
    public BO.BO_GetValues BO_GetValues_Instanse {get;}

    public SerialPortInitControl()
    {
        InitializeComponent();
        BO_Instanse = new BO();
        BO_GetValues_Instanse = new BO.BO_GetValues();
    }


    public bool GetValues(out BO.BO_GetValues values, ref string errorMessage)
    {
        if(BO_Instanse == null)//need real code here
        { 
            values = new BO.BO_GetValues()
            {
                name = CBX_Name.Text,
                baudRate = CBX_BaudRate.Text,
                paritie = CBX_Parity.Text,
                dataBits = CBX_DataBits.Text,
                stopBits = CBX_StopBits.Text,
            };

            return true;
        }
        else
        {
            values = null;
            errorMessage = "Checking failed! " + errorMessage;
            return false;
        }
    }
}

因此,这将有效:

var control = new SerialPortInitControl();
var bo = control.BO_Instanse;
var bo_values = control.BO_GetValues_Instanse;

您也可以在没有USERCORTROL类的情况下创建类的实例:

 var boInstanse = new SerialPortInitControl.BO();
 var boGetValues_Instanse = new SerialPortInitControl.BO.BO_GetValues();

Your UserControl hasn't instance of BO class. You just define BO class inside SerialPortInitControl, so when you will create instanse of it, it will be like this:

var instBO = new SerialPortInitControl.BO.BO_GetValues()

so, you created object of BO class, but when you stored it in UserConrol?

public partial class SerialPortInitControl : UserControl
{
    public class BO
    {
        public class BO_GetValues
        {
            public string name;
            public string baudRate;
            public string paritie;
            public string dataBits;
            public string stopBits;
        }
    }

    //instance of BO class
    public BO BO_Instanse {get;}
    
    //instance of BO.Get_Values class
    public BO.BO_GetValues BO_GetValues_Instanse {get;}

    public SerialPortInitControl()
    {
        InitializeComponent();
        BO_Instanse = new BO();
        BO_GetValues_Instanse = new BO.BO_GetValues();
    }


    public bool GetValues(out BO.BO_GetValues values, ref string errorMessage)
    {
        if(BO_Instanse == null)//need real code here
        { 
            values = new BO.BO_GetValues()
            {
                name = CBX_Name.Text,
                baudRate = CBX_BaudRate.Text,
                paritie = CBX_Parity.Text,
                dataBits = CBX_DataBits.Text,
                stopBits = CBX_StopBits.Text,
            };

            return true;
        }
        else
        {
            values = null;
            errorMessage = "Checking failed! " + errorMessage;
            return false;
        }
    }
}

So, this will works:

var control = new SerialPortInitControl();
var bo = control.BO_Instanse;
var bo_values = control.BO_GetValues_Instanse;

Also you can create instances of you classes without UserControl class:

 var boInstanse = new SerialPortInitControl.BO();
 var boGetValues_Instanse = new SerialPortInitControl.BO.BO_GetValues();

进入USERCORTROL的课程(C#Winforms)

若水微香 2025-02-16 22:59:52

模拟 auth0.useauth0

要访问模块的模块,以通配符导入导入整个模块,并避免命名导入。另外, vi.mocked() 支持。它没有模拟任何东西。

而不是这样

import { useAuth0 } from '@auth0/auth0-vue' ❌

vi.mock('@auth0/auth0-vue')
const mockedUseAuth0 = vi.mocked(useAuth0, true) ❌

import * as auth0 from '@auth0/auth0-vue' ✅

vi.mock('@auth0/auth0-vue')

describe('NavBar.vue', () => {
it('does something', async () => {

Mocking auth0.useAuth0

To access the mocked module, import the whole module with a wildcard import, and avoid named imports. Also, vi.mocked() is just a helper for TypeScript support. It doesn't mock anything.

So instead of this:

import { useAuth0 } from '@auth0/auth0-vue' ❌

vi.mock('@auth0/auth0-vue')
const mockedUseAuth0 = vi.mocked(useAuth0, true) ❌

...do this:

import * as auth0 from '@auth0/auth0-vue' ✅

vi.mock('@auth0/auth0-vue')

Then, mock useAuth0 by attaching a property directly to the mocked auth0 import:

describe('NavBar.vue', () => {
  it('does something', async () => {
                      ????
    (auth0 as any).useAuth0 = vi.fn().mockReturnValue({
      // relevant fields for test
    });
  })
})

The value of useAuth0 should be a mock function (vi.fn()) that returns the fields relevant to the test. Assuming the component under test is NavBar.vue from Auth0's sample app, one could write a test to verify the login button calls loginWithRedirect. That button is only available when isAuthenticated and isLoading are false. Note the fields do not need to be Vue refs.

So such a test could look like this:

describe('NavBar.vue', () => {
  it('login button invokes useAuth.loginWithRedirect', async () => {
    const loginWithRedirect = vi.fn();
    (auth0 as any).useAuth0 = vi.fn().mockReturnValue({
      isAuthenticated: false,
      isLoading: false,
      loginWithRedirect,
    });

    const wrapper = shallowMount(NavBar);
    await wrapper.find('button#qsLoginBtn').trigger('click');

    expect(auth0.useAuth0).toHaveBeenCalled();
    expect(loginWithRedirect).toHaveBeenCalled();
  })
})

Mocking useAuth().user

One could also write a test to verify the authenticated user's details are shown in the component. Specifically, the user's name is shown in .user-info, and the user's picture is shown in .user-info img when isAuthenticated is true. The mocked useAuth0 should thus return isAuthenticated and user as follows:

describe('NavBar', () => {
  it('authenticated user details are shown', async () => {
    const user = {
      name: '[email protected]',
      picture: 'https://s.gravatar.com/avatar/1f9d9a9efc2f523b2f09629444632b5c?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fjo.png',
    };

    (auth0 as any).useAuth0 = vi.fn().mockReturnValue({
      isAuthenticated: true,
      user,
    });

    const wrapper = shallowMount(NavBar);

    expect(wrapper.find('.user-info').text()).toBe(user.name);
    expect(wrapper.find('.user-info img').attributes('src')).toBe(user.picture);
  })
})

demo

VUE:如何模拟Auth0进行vitest测试

若水微香 2025-02-16 22:40:19

我做到了:

  1. 我创建了2位作家,并与CompositeItemWriter联系在一起,
  2. 我通过DTO传递了DTO,参考失败或/和成功处理的参考数据的错误。
  3. DTO仅用于通过处理器向作家。
  4. 每个作者都检查DTO是否具有您各自的数据。如果有成功数据,请进行成功数据,否则返回。如果有错误数据,请进行工作错误数据,否则返回。 CompositeItemwriter将始终致电其中的所有作家。

需要明确的是,就我而言,我有一个读者可以从表中读取信息。处理信息的处理器池,最后填充了DTO。 DTO仅用于从处理器到CompositeItemWriter的信息。 DTO提到了两个对象,一个是成功的,另一个是错误的。每个作家都检查了其在DTO上的领域。

也许可以定义也为您的情况。这将是最优雅的方式,但是您必须研究文档以查看实施它的最佳方法。

I did that:

  1. I created 2 writers and tie them with a CompositeItemWriter
  2. I pass a DTO with reference to the error for failure or/and the reference data processed with success.
  3. The DTO is only for passing through processor to writers.
  4. Each writer check if DTO has your respective data. If success data is there, work success data, otherwise return. If error data is there, work error data, otherwise return. CompositeItemWriter will always call all writers inside of it.

To be clear, in my case I had a reader that read information from a table. A pool of processors that processed the information, and at the end, populated a DTO. The DTO was only for take information from the processor to the CompositeItemWriter. The DTO had reference to two objects, one for success and another for error. Each writer checked its field on the DTO.

Maybe is possible to define Spring Batch Flow for your case as well. It would be the most elegant way, but you have to study the documentation to see the best way to implement it.

基于处理器结果的运行时作者在春季批处理

若水微香 2025-02-16 08:41:50

在公式的一般规则中,您可以在公式下方用户

=INDEX($A$1:$C$4,ROW(A1),COUNTA(A1:C1))

- ”在此处输入图像说明”

In general rules of formula you can user below formula-

=INDEX($A$1:$C$4,ROW(A1),COUNTA(A1:C1))

enter image description here

在每行的Google表上获取最后一个非空的专栏

若水微香 2025-02-15 18:13:27

没有类型的意思是“任何功能”;例如, int-&gt;真实字符串 - &gt; bool 是完全独立的类型,也无法创建两者之间模棱两可的类型。

但是,您可以创建类型函数采用两种类型并返回适当的记录类型:

type ('a, 'b) subject = {algorithm: 'a -> 'b, id: string}

在上述声明之后,(int,real)主题(例如)(例如)将意味着 {算法:int-&gt;真实,ID:字符串}

使用“ alpha”和“ beta”类型的正确方法?如果是这样,如何指这些类型?

是的 - “ alpha”和“ beta”正是您发音'a 'b 的方式。它们不是一个单独的概念。 :-)

There's no type that means "any function"; for example, int -> real and string -> bool are completely separate types, and there's no way to create a type that's ambiguous between the two of them.

However, you can create a type function that takes two types and returns the appropriate record type:

type ('a, 'b) subject = {algorithm: 'a -> 'b, id: string}

After the above declaration, (int, real) subject (for example) will mean {algorithm: int -> real, id: string}.

Is using "alpha" and "beta" types the correct way to do this? If so, how does one refer to these types?

Yes — "alpha" and "beta" are just how you pronounce 'a and 'b, respectively. They're not a separate concept. :-)

如何声明与标准ML中任何功能匹配的类型?

若水微香 2025-02-15 07:30:01

此代码将帮助您对UserAction和LoginScreen进行一些更改。

UserAction:

import axios from 'axios'
import {
    USER_LOGIN_REQUEST,
    USER_LOGIN_SUCCESS,
    USER_LOGIN_FAIL,
    USER_LOGOUT,
} from '../constants/userConstants'

export const login = (email, password) => async (dispatch) => {
    try {
        dispatch({
            type: USER_LOGIN_REQUEST
        })

        const config = {
            headers: {
                'Content-type': 'application/json'
            }
        }

        const { data } = await axios.post(
            `api/users/login`,
            { 'username': email, 'password': password },
            config
        )

        dispatch({
            type: USER_LOGIN_SUCCESS,
            payload: data
        })

        localStorage.setItem('userInfo', JSON.stringify(data))

    } catch (error) {
        dispatch({
            type: USER_LOGIN_FAIL,
            payload: error.response && error.response.data.detail
                ? error.response.data.detail
                : error.message,
        })
    }
}

这是LoginScreen:

import React, { useState, useEffect } from 'react'
import { Link, useHistory, useLocation } from 'react-router-dom'
import { Form, Button, Row, Col } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import Loader from '../components/Loader'
import Message from '../components/Message'
import FormContainer from '../components/FormContainer'
import { login } from '../actions/userActions'

function LoginScreen() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const history = useHistory()
  const location = useLocation

  const dispatch = useDispatch()


  const redirect = location.search ? location.search.split('=')[1] : '/'

  const userLogin = useSelector(state => state.userLogin)
  const { error, loading, userInfo } = userLogin

  useEffect(() => {
    if (userInfo) {
      history.push(redirect)
    }
  }, [history, userInfo, redirect])

  const submitHandler = (e) => {
    e.preventDefault()
    dispatch(login(email, password))
  }

  return (
    <FormContainer>
      <h1>Sign In</h1>
      {error && <Message variant='danger'>{error}</Message>}
      {loading && <Loader />}
      <Form onSubmit={submitHandler}>

        <Form.Group controlId='email'>
          <Form.Label>Email Address</Form.Label>
          <Form.Control
            type='email'
            placeholder='Enter Email'
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          >
          </Form.Control>
        </Form.Group>


        <Form.Group controlId='password'>
          <Form.Label>Password</Form.Label>
          <Form.Control
            type='password'
            placeholder='Enter Password'
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          >
          </Form.Control>
        </Form.Group>

        <Button type='submit' variant='primary'>
          Sign In
        </Button>
      </Form>

      <Row className='py-3'>
        <Col>
          New Customer? <Link
            to={redirect ? `/register?redirect=${redirect}` : '/register'}>
            Register
          </Link>
        </Col>
      </Row>

    </FormContainer>
  )
}

export default LoginScreen

This code will help you do some changing in userAction and LoginScreen.

userAction:

import axios from 'axios'
import {
    USER_LOGIN_REQUEST,
    USER_LOGIN_SUCCESS,
    USER_LOGIN_FAIL,
    USER_LOGOUT,
} from '../constants/userConstants'

export const login = (email, password) => async (dispatch) => {
    try {
        dispatch({
            type: USER_LOGIN_REQUEST
        })

        const config = {
            headers: {
                'Content-type': 'application/json'
            }
        }

        const { data } = await axios.post(
            `api/users/login`,
            { 'username': email, 'password': password },
            config
        )

        dispatch({
            type: USER_LOGIN_SUCCESS,
            payload: data
        })

        localStorage.setItem('userInfo', JSON.stringify(data))

    } catch (error) {
        dispatch({
            type: USER_LOGIN_FAIL,
            payload: error.response && error.response.data.detail
                ? error.response.data.detail
                : error.message,
        })
    }
}

This is LoginScreen:

import React, { useState, useEffect } from 'react'
import { Link, useHistory, useLocation } from 'react-router-dom'
import { Form, Button, Row, Col } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import Loader from '../components/Loader'
import Message from '../components/Message'
import FormContainer from '../components/FormContainer'
import { login } from '../actions/userActions'

function LoginScreen() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const history = useHistory()
  const location = useLocation

  const dispatch = useDispatch()


  const redirect = location.search ? location.search.split('=')[1] : '/'

  const userLogin = useSelector(state => state.userLogin)
  const { error, loading, userInfo } = userLogin

  useEffect(() => {
    if (userInfo) {
      history.push(redirect)
    }
  }, [history, userInfo, redirect])

  const submitHandler = (e) => {
    e.preventDefault()
    dispatch(login(email, password))
  }

  return (
    <FormContainer>
      <h1>Sign In</h1>
      {error && <Message variant='danger'>{error}</Message>}
      {loading && <Loader />}
      <Form onSubmit={submitHandler}>

        <Form.Group controlId='email'>
          <Form.Label>Email Address</Form.Label>
          <Form.Control
            type='email'
            placeholder='Enter Email'
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          >
          </Form.Control>
        </Form.Group>


        <Form.Group controlId='password'>
          <Form.Label>Password</Form.Label>
          <Form.Control
            type='password'
            placeholder='Enter Password'
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          >
          </Form.Control>
        </Form.Group>

        <Button type='submit' variant='primary'>
          Sign In
        </Button>
      </Form>

      <Row className='py-3'>
        <Col>
          New Customer? <Link
            to={redirect ? `/register?redirect=${redirect}` : '/register'}>
            Register
          </Link>
        </Col>
      </Row>

    </FormContainer>
  )
}

export default LoginScreen

用户登录(PIN) - &GT;错误(PIN):“请求失败,状态代码404”

更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

更多

友情链接

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文