Javascript 组件更新时始终返回相同的道具和状态
我找到了很多解决这个问题的方法,但都不管用 我有一个根据后端响应动态呈现组件的视图Javascript 组件更新时始终返回相同的道具和状态,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我找到了很多解决这个问题的方法,但都不管用 我有一个根据后端响应动态呈现组件的视图 /** * Module dependencies */ const React = require('react'); const Head = require('react-declarative-head'); const MY_COMPONENTS = { text: require('../components/fields/Description'), initiatives: requ
/**
* Module dependencies
*/
const React = require('react');
const Head = require('react-declarative-head');
const MY_COMPONENTS = {
text: require('../components/fields/Description'),
initiatives: require('../components/fields/Dropdown'),
vuln: require('../components/fields/Dropdown'),
severities: require('../components/fields/Dropdown'),
};
const request = restclient({
timeout: 5000,
baseURL: '/api',
});
const { DropdownItem } = Dropdown;
class CreateView extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false,
states: props.states,
error: props.error,
spinner: true,
state: props.state,
prevState: '',
components: [],
};
this.handleChange = this.handleChange.bind(this);
this.getRequiredFields = this.getRequiredFields.bind(this);
this.onChangeHandler = this.onChangeHandler.bind(this);
this.changeState = this.changeState.bind(this);
this.loadComponents = this.loadComponents.bind(this);
}
componentDidMount() {
this.loadComponents();
}
onChangeHandler(event, value) {
this.setState((prevState) => {
prevState.prevState = prevState.state;
prevState.state = value;
prevState.spinner = true;
return prevState;
}, () => {
this.getRequiredFields();
});
}
getRequiredFields() {
request.get('/transitions/fields', {
params: {
to: this.state.state,
from: this.state.prevState,
},
})
.then((response) => {
const pComponents = this.state.components.map(c => Object.assign({}, c));
pComponents.forEach((c) => {
c.field.required = 0;
c.field.show = false;
});
response.data.forEach((r) => {
const ob = pComponents.find(c => c.field.name === r.name);
if (ob) {
ob.field.required = r.required;
ob.field.show = true;
}
});
this.setState({
components: pComponents,
fields: response.data,
spinner: false,
});
})
.catch(err => err);
}
loadComponents() {
this.setState((prevState) => {
prevState.components = Object.keys(MY_COMPONENTS).map((k) => {
const field = {
name: k,
required: 0,
show: true,
};
return {
field, component: MY_COMPONENTS[k],
};
});
return prevState;
});
}
handleChange(field, value) {
this.setState((prevState) => {
prevState[field] = value;
return prevState;
});
}
changeState(field, value) {
this.setState((prevState) => {
prevState[`${field}`] = value;
return prevState;
});
}
render() {
const Components = this.state.components;
return (
<Page name="CI" state={this.props} Components={Components}>
<Script src="vendor.js" />
<Card className="">
<div className="">
<div className="">
<Spinner
show={this.state.spinner}
/>
{Components.map((component, i) => {
const Comp = component.component;
return (<Comp
key={i}
value={this.state[component.field.name]}
field={component.field}
handleChange={this.handleChange}
modal={this.state.modal}
changeState={this.changeState}
/>);
})
}
</div>
</div>
</div>
</Card>
</Page>
);
}
}
module.exports = CreateView;
/**
*模块依赖关系
*/
const React=require('React');
const Head=require('react-declarative-Head');
常量MY_组件={
text:require(“../components/fields/Description”),
方案:需要(“../components/fields/Dropdown”),
vuln:require(“../components/fields/Dropdown”),
严重性:要求(“../components/fields/Dropdown”),
};
const request=restclient({
超时:5000,
baseURL:“/api”,
});
const{DropdownItem}=下拉列表;
类CreateView扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
莫代尔:错,
国家:道具,国家,
错误:props.error,
斯宾纳:没错,
状态:props.state,
prevState:“”,
组成部分:[],
};
this.handleChange=this.handleChange.bind(this);
this.getRequiredFields=this.getRequiredFields.bind(this);
this.onChangeHandler=this.onChangeHandler.bind(this);
this.changeState=this.changeState.bind(this);
this.loadComponents=this.loadComponents.bind(this);
}
componentDidMount(){
这是loadComponents();
}
onChangeHandler(事件、值){
this.setState((prevState)=>{
prevState.prevState=prevState.state;
prevState.state=值;
prevState.spinner=true;
返回状态;
}, () => {
这是.getRequiredFields();
});
}
getRequiredFields(){
request.get(“/transitions/fields”{
参数:{
致:this.state.state,
发件人:this.state.prevState,
},
})
。然后((响应)=>{
constpcomponents=this.state.components.map(c=>Object.assign({},c));
pComponents.forEach((c)=>{
c、 field.required=0;
c、 field.show=false;
});
response.data.forEach((r)=>{
const ob=pComponents.find(c=>c.field.name==r.name);
如果(ob){
ob.field.required=r.required;
ob.field.show=true;
}
});
这是我的国家({
组件:P组件,
字段:response.data,
纺纱工:错,
});
})
.catch(err=>err);
}
loadComponents(){
this.setState((prevState)=>{
prevState.components=Object.keys(我的组件).map((k)=>{
常量字段={
姓名:k,,
必填项:0,
秀:没错,
};
返回{
字段,组件:MY_组件[k],
};
});
返回状态;
});
}
handleChange(字段、值){
this.setState((prevState)=>{
prevState[字段]=值;
返回状态;
});
}
变更状态(字段、值){
this.setState((prevState)=>{
prevState[`${field}`]=值;
返回状态;
});
}
render(){
常量组件=this.state.Components;
返回(
{Components.map((component,i)=>{
const Comp=component.component;
返回();
})
}
);
}
}
module.exports=CreateView;
和下拉组件
const React = require('react');
const request = restclient({
timeout: 5000,
baseURL: '/api',
});
const { DropdownItem } = Dropdown;
class DrpDwn extends React.Component {
constructor(props) {
super(props);
this.state = {
field: props.field,
values: [],
};
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('state', this.state.field);
console.log('prevState', prevState.field);
console.log('prevProps', prevProps.field);
console.log('props', this.props.field);
}
render() {
const { show } = this.props.field;
return (show && (
<div className="">
<Dropdown
className=""
onChange={(e, v) => this.props.handleChange(this.props.field.name, v)}
label={this.state.field.name.replace(/^./,
str => str.toUpperCase())}
name={this.state.field.name}
type="form"
value={this.props.value}
width={100}
position
>
{this.state.values.map(value => (<DropdownItem
key={value.id}
value={value.name}
primary={value.name.replace(/^./, str => str.toUpperCase())}
/>))
}
</Dropdown>
</div>
));
}
module.exports = DrpDwn;
const React=require('React');
const request=restclient({
超时:5000,
baseURL:“/api”,
});
const{DropdownItem}=下拉列表;
类DrpDwn扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
场:道具场,
值:[],
};
}
componentDidUpdate(prevProps、prevState、快照){
console.log('state',this.state.field);
console.log('prevState',prevState.field);
console.log('prevProps',prevProps.field);
console.log('props',this.props.field);
}
render(){
const{show}=this.props.field;
返回(显示和显示)(
this.props.handleChange(this.props.field.name,v)}
label={this.state.field.name.replace(/^./,
str=>str.toUpperCase())}
name={this.state.field.name}
type=“form”
value={this.props.value}
宽度={100}
位置
>
{this.state.values.map(value=>(str.toUpperCase())}
/>))
}
));
}
module.exports=DrpDwn;
代码实际上是有效的,它可以正确地隐藏或显示组件,但问题是我不能在componentdiddupdate
内执行任何操作,因为prevProps
prevState
和props
总是相同的
我想问题是我总是在变异同一个对象,但我找不到方法
我要做的是填写下拉项
Ps:“真正”的代码是有效的,我修改它是为了在这里发布它 React状态应该是不可变的。由于您正在改变状态,因此无法判断状态是否已更改。特别是,我认为这是造成您问题的主要原因:
this.setState((prevState) => {
prevState.components = Object.keys(MY_COMPONENTS).map((k) => {
const field = {
name: k,
required: 0,
show: true,
}; return {
field, component: MY_COMPONENTS[k],
};
});
return prevState;
});
可以修改以前的状态以更改其components属性。而是创建一个新状态:
this.setState(prevState => {
const components = Object.keys(MY_COMPONENTS).map((k) => {
const field = {
name: k,
required: 0,
show: true,
};
return {
field, component: MY_COMPONENTS[k],
};
});
return { components }
}
你有一个额外的地方,你是变异状态。我不知道这是否导致了您的特殊问题,但无论如何值得一提:
const pComponents = [].concat(this.state.components);
// const pComponents = [...this.state.components];
pComponents.forEach((c) => {
c.field.required = 0;
c.field.show = false;
});
response.data.forEach((r) => {
const ob = pComponents.find(c => c.field.name === r.name);
if (ob) {
ob.field.required = r.required;
ob.field.show = true;
}
});
您可以创建state.components的副本,但这只是一个浅副本。该数组是一个新数组,但数组中的对象是旧对象。因此,当您设置ob.field.required时,您正在改变旧状态和新状态
如果要更改对象中的特性,则需要在进行更改的每个级别复制这些对象。扩展语法通常是最简洁的方法:
let pComponents = this.state.components.map(c => {
return {
...c,
field: {
...c.field,
required: 0,
show: false
}
}
});
response.data.forEach(r => {
const ob = pComponents.find(c => c.field.name === r.name);
if (ob) {
// Here it's ok to mutate, but only because i already did the copying in the code above
ob.field.required = r.required;
ob.field.show = true;
}
})
你提到的第一件事是正确的,我不知道我在做什么,但不是解决方案