【发布时间】:2021-07-30 18:08:48
【问题描述】:
我是新来的反应并且已经被困在这个问题上两天了。登录时,您可以选择客户或商家并重定向到适当的位置。我需要将数据从客户端传递到商家端,但是虽然客户端在输入中提交时会更新,但商家端不会。即使组件有不同的路线,有什么办法可以做到这一点?我正在尝试使用的是 redux 商店,但这似乎不起作用。
src/client/FirstForm.js
import React, {createRef, useState} from "react";
import { useDispatch, useSelector } from 'react-redux'
import { addBird, incrementBird } from '../store/birds/birds';
import {connect} from 'react-redux';
function FirstForm() {
const handleInputChange = (event) => {
event.preventDefault();
this.setState({
prodDetails : event.target.value
})
}
const [birdName, setBird] = useState('');
const birds = useSelector(state => state.birds);
const dispatch = useDispatch();
const handleSubmit = event => {
event.preventDefault();
dispatch(addBird(birdName))
setBird('');
};
return (
<div className="input-container" id="subtitle-space">
<input type="text"onChange={e => setBird(e.target.value)} value={birdName}/>
<button type="submit" className="btn" onClick={handleSubmit}>
</div>
);
}
const mapStateToProps= state => {
return {
birds : state.birds
}
}
const mapDispatchToProps = dispatch => {
return {
addBird: () => dispatch(addBird())
}
}
export default connect(mapStateToProps,mapDispatchToProps)(FirstForm);
src/merchant/Merchant.js
function Merchant(props) {
const birds = useSelector(state => state.birds);
const dispatch = useDispatch();
return (
<div className="placeholder">
<h>{birds.map(bird => (<h>{bird.name} <br></br></h>))}</h>
<div> )
);
}
export default withRouter(Merchant);
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {Provider} from 'react-redux';
import { createStore } from 'redux';
import birdApp from './store/birds/birds';
const store = createStore(birdApp);
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers:
serviceWorker.unregister();
src/store/birds.js
import { combineReducers } from 'redux';
const ADD_BIRD = 'ADD_BIRD';
const INCREMENT_BIRD = 'INCREMENT_BIRD';
export function addBird(bird) {
return {
type: ADD_BIRD,
bird,
}
}
export function incrementBird(bird) {
return {
type: INCREMENT_BIRD,
bird
}
}
const defaultBirds = [
{
name: 'robin',
views: 1,
}
];
function birds(state=defaultBirds, action) {
switch (action.type) {
case ADD_BIRD:
state.push(
{
name: action.bird,
views: 1
})
return state
case INCREMENT_BIRD:
const bird = state.find(b => action.bird === b.name);
const birds = state.filter(b => action.bird !== b.name);
return [
...birds,
{
...bird,
views: bird.views + 1
}
];
default:
return state;
}
}
const birdApp = combineReducers({
birds
});
export default birdApp;
这也是我的客户端组件 src/client/client.js:
import React,{ useEffect } from 'react'; //for later security
import { withRouter } from 'react-router-dom';
import './Client.css';
import '../common/Button.css';
import '../common/TopBar.css';
import Boxes from './Boxes';
import FirstForm from './FirstForm';
import SecondForm from './SecondForm';
import ThirdForm from './ThirdForm';
import RequestNow from './RequestNow';
class Client extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return(
<div>
{/* Request now button */}
<RequestNow></RequestNow>
{/* Boxes in middle */}
<Boxes></Boxes>
{/* Request now first form */}
<FirstForm></FirstForm>
{/* Request now second form */}
<SecondForm></SecondForm>
<ThirdForm></ThirdForm>
</div>
)
}
}
export default withRouter(Client);
这是登录表单 src/components/loginform/LoginForm.js
import React, {useState} from 'react';
import axios from 'axios';
import {API_BASE_URL, ACCESS_TOKEN_NAME} from '../../constants/apiContants';
import { withRouter } from "react-router-dom";
import "../../common/Button.css";
import "../../common/Security.css";
function LoginForm(props) {
const [state , setState] = useState({
email : "",
password : "",
successMessage: null,
client : false,
merchant : false
})
const handleChange = (e) => {
const {id , value} = e.target
setState(prevState => ({
...prevState,
[id] : value
}))
}
const redirectToClient = () => {
props.updateTitle('Client')
props.history.push('/client');
}
const redirectToMerchant = () => {
props.updateTitle('Merchant')
props.history.push('/merchant');
}
const handleClient = () => {
//Only select if client is unselected
if(state.client === false) {
state.client = true;
state.merchant = false;
document.getElementById("client").className = "left button-selected";
document.getElementById("merchant").className = "right button-unselected";
}
}
const handleMerchant = () => {
//Do nothing if merchant is already selected
if(state.merchant === false) {
state.merchant = true;
state.client = false;
document.getElementById("merchant").className = "right button-selected";
document.getElementById("client").className = "left button-unselected";
}
}
const handleSubmitClick = (e) => {
e.preventDefault();
if(state.client === false && state.merchant === false) {
props.showError('Please select client or merchant');
}
else {
const payload={
"email":state.email,
"password":state.password,
}
axios.post(API_BASE_URL+'/user/login', payload)
.then(function (response) {
if(response.status === 200){
setState(prevState => ({
...prevState,
'successMessage' : 'Login successful. Redirecting to home page..'
}))
localStorage.setItem(ACCESS_TOKEN_NAME,response.data.token);
if(state.client) {
redirectToClient();
}
else if(state.merchant) {
redirectToMerchant();
}
props.showError(null)
}
else if(response.code === 204){
props.showError("Username and password do not match");
}
else{
props.showError("Username does not exists");
}
})
.catch(function (error) {
console.log(error);
});
}}
const redirectToRegister = () => {
props.history.push('/register');
props.updateTitle('Register');
}
return(
<div className="card col-12 col-lg-4 login-card mt-2 hv-center">
<form>
<div className="form-group text-left">
<label htmlFor="exampleInputEmail1">Email address</label>
<input type="email"
className="form-control"
id="email"
aria-describedby="emailHelp"
placeholder="Enter email"
value={state.email}
onChange={handleChange}
/>
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group text-left">
<label htmlFor="exampleInputPassword1">Password</label>
<input type="password"
className="form-control"
id="password"
placeholder="Password"
value={state.password}
onChange={handleChange}
/>
</div>
<div className="form-check">
</div>
<div className="btnContainer" id="clientMerchButton">
<span id="client" class="left button-unselected"
onClick={handleClient}>
Client</span>
<span id="merchant" class="right button-unselected"
onClick={handleMerchant}>
Merchant</span>
</div> <br></br> <br></br>
<button
type="submit"
className="btn btn-primary"
id="loginSubmit"
onClick={handleSubmitClick}
>Submit</button>
</form>
<div className="alert alert-success mt-2" style={{display: state.successMessage ? 'block' : 'none' }} role="alert">
{state.successMessage}
</div>
<div className="registerMessage">
<span>Dont have an account? </span>
<span className="loginText" onClick={() => redirectToRegister()}>Register</span>
</div>
</div>
)
}
export default withRouter(LoginForm);
【问题讨论】:
-
据我了解,您有两条路线:
merchant和client,您能否同时发布您的router组件和client组件,并告诉我们您的数据是什么想通过吗? -
我已经编辑了我的帖子。现在我只是想通过更新的鸟类数组作为测试(它有一个名称和视图)。提交到 FirstForm.js 中的表单应该将元素添加到 Birds 数组,并且此更新不会显示在商家端,即使它确实出现在客户端 FirstForm 上。
-
很抱歉我还没有发现问题,但我注意到奇怪的 jsx 元素 'h'
<h>{birds.map(bird => (<h>{bird.name} <br></br></h>))}</h>,你的意思是h1?,你能尝试在您的Merchant组件中也控制台记录birds变量,看看您有什么。 -
那只是在客户端显示鸟类列表的所有元素。当我在商家端 console.log(birds) 时,我得到的只是鸟的初始状态,它只是 {name : 'robin', value : 1} 没有添加额外的鸟
-
您在
Merchant中的代码看起来不错,但您可以尝试使用connect函数而不是useSelector以确保``` function Merchant(props){ console.log( {props}) //... } const mapStateToProps= state => { return { bird : state.birds } } export default withRouter(connect(mapStateToProps)(Merchant)); ```
标签: javascript reactjs react-native redux react-hooks