我有两个不同的单选按钮,它们会在onChange上触发功能。 我有两个属性:selectedLabel和selectedTestdata。 我想在触发函数时更改这些属性的值。
我收到一条错误消息,提示我无法更改只读属性。
这是我的代码:
import React, { useState, Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import './styles.css'
import { bindActionCreators } from 'redux';
import PropTypes from 'prop-types';
import { testdataRequest } from '../../actions/testdata'
import { labelsRequest } from '../../actions/labels'
....
export class TemplateDetails extends Component {
componentDidMount() {
this.props.testdataRequestConnect(this.props.match.params.templateid, this.props.match.params.locale);
this.props.labelsRequestConnect(this.props.match.params.templateid);
}
testDataReloader = (e) => {
this.props.selectedTestdata = e.target.value;
console.log(e.target.value);
}
labelsReloader = event => {
console.log(JSON.parse(event.target.value));
}
renderTestdata() {
const { testdata } = this.props;
if (!testdata.length) {
return (
<span
data-at="no-customers"
className="pos-v-center pos-left pos-right pos-absolute t-center t-light-grey">
<span className="d-block t-1 t-bold">No testdata found</span>
</span>
);
}
return (
<div
style={{ flexGrow: '1', flexShrink: '1' }}
className="t-left ox-hidden oy-hidden"
data-at="customer-search-list">
{testdata.map((data, index) => (
<div key={data}>
<div className="form-element type-radio">
<span className="box-toggler">
<input onChange={this.testDataReloader} value={data} type="radio" name="radio-testdata" className="form-input" id={index}/>
<span className="indicator"></span>
</span>
<label htmlFor={index} className="form-placeholder">{data}</label>
<span className="icon icon--sm pos-absolute pos-right pos-v-center">
<svg title="icon--arrow-small-right" role="img">
<use xmlnsXlink="http://www.w3.org/1999/xlink" xlinkHref="#icon--arrow-small-right" />
</svg>
</span>
</div>
</div>
))}
</div>
);
}
renderLabels() {
const { labels } = this.props;
if (!labels.length) {
return (
<span
data-at="no-customers"
className="pos-v-center pos-left pos-right pos-absolute t-center t-light-grey">
<span className="d-block t-1 t-bold">No labels found</span>
</span>
);
}
return (
<div
style={{ flexGrow: '1', flexShrink: '1' }}
className="t-left"
data-at="customer-search-list">
{labels.map((data, index) => (
<div key={data.uuid}>
<div className="form-element type-radio">
<span className="box-toggler">
<input onChange={this.labelsReloader} value={JSON.stringify(data)} type="radio" name="radio-labels" className="form-input" id={data.uuid}/>
<span className="indicator"></span>
</span>
<label htmlFor={data.uuid} className="form-placeholder">{data.values.creationTime}</label>
<span className="icon icon--sm pos-absolute pos-right pos-v-center">
<svg title="icon--arrow-small-right" role="img">
<use xmlnsXlink="http://www.w3.org/1999/xlink" xlinkHref="#icon--arrow-small-right" />
</svg>
</span>
</div>
</div>
))}
</div>
);
}
render() {
const { isFetchingTestdata, errorTestdata, isFetchingLabels, errorLabels } = this.props;
return (
<div className="pos-relative h-100 o-hidden">
<div className="d-flex h-100 w-100 pos-relative">
<div className="col-4 p-0">
<div className="d-flex flex-column h-100 pl-4 pb-4">
<div
className="px-2 mt-4 w-100"
style={{ maxWidth: '500px' }}>
<Link to="/templates">
<Button variant="link">
<span className="t-1" style={{ lineHeight: '1' }}>‹</span> Templates
</Button>
</Link>
</div>
{/* Test data */}
<div className="d-flex flex-wrap align-content-start py-2 pos-relative bg-white shadow t-center mt-4 p-4 w-100 h-100" style={{ flexGrow: '1', overflowY: 'scroll' }}>
<div className="w-100" style={{ height: 'fit-content' }}>
{errorTestdata && <Alert variant="error">{errorTestdata}</Alert>}
<h1>Test data</h1>
<p className="t-grey mb-4">
Available testdata
<span className="d-block">Select one to render the template with it</span>
</p>
</div>
{isFetchingTestdata ? <span className="throbber" /> : this.renderTestdata()}
</div>
{/* Labels */}
<div className="d-flex flex-wrap py-2 pos-relative bg-white shadow t-center mt-4 p-4 w-100 h-100" style={{ flexGrow: '1', overflowY: 'scroll' }}>
<div className="w-100">
<h1>Labels</h1>
<p className="t-grey mb-4">
{errorLabels && <Alert variant="error">{errorLabels}</Alert>}
Available labels
<span className="d-block">Select one to render the template with them</span>
</p>
</div>
{isFetchingLabels ? <span className="throbber" /> : this.renderLabels()}
</div>
</div>
</div>
<div className="col-8 mr-4">
<div className="d-flex flex-column h-100 pl-4 pb-4 pr-4">
<div className="d-flex flex-column bg-white shadow t-left p-4 mt-4 w-100 h-100" style={{ minHeight: '20px', maxHeight: '70px' }}>
<div className="w-100 h-100 mb-2">
<h1 className="mb-2">Subject </h1>
</div>
</div>
<div className="d-flex flex-column bg-white shadow t-center p-4 mt-4 w-100 h-100">
<div>
<h1>Template</h1>
<p className="t-grey mb-4">
Live preview of the template
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
TemplateDetails.propTypes = {
isFetchingTestdata: PropTypes.bool,
isFetchingLabels: PropTypes.bool,
errorTestdata: PropTypes.string,
errorLabels: PropTypes.string,
selectedLabel: PropTypes.string,
selectedTestdata: PropTypes.string,
templatesRequestConnect: PropTypes.func,
labelsRequestConnect: PropTypes.func,
testdata: PropTypes.array,
labels: PropTypes.array,
};
TemplateDetails.defaultProps = {
isFetchingTestdata: false,
isFetchingLabels: false,
errorTestdata: '',
errorLabel: '',
selectedLabel: '',
selectedTestdata: '',
templatesRequestConnect: () => { },
labelsRequestConnect: () => { },
testdata: [],
labels: [],
};
export default connect(
(state) => ({
isFetchingTestdata: state.testdataStore.isFetching,
errorTestdata: state.testdataStore.error,
testdata: state.testdataStore.testdata,
isFetchingLabels: state.labelsStore.isFetching,
errorLabels: state.labelsStore.error,
labels: state.labelsStore.labels,
}),
(dispatch) => bindActionCreators({
testdataRequestConnect: testdataRequest,
labelsRequestConnect: labelsRequest,
}, dispatch),
)(TemplateDetails);
答案 0 :(得分:3)
props
are read-only,而您尝试分配给它:
testDataReloader = e => {
// this.props.selectedTestdata = e.target.value;
console.log(e.target.value);
};
关于为什么不能更改道具on Stack Overflow,您有很多类似的讨论。
答案 1 :(得分:0)
您不能直接更改道具,因为道具是只读的。为了获得结果,您采用了不同的方法。
您可以做的一件事情是,可以传递selectedTestdata,而可以通过父组件传递一个方法作为道具,该道具将负责更改您的父状态值。
例如 在父组件中
<Child selectedTestdata={this.state.selectedTestdata} udpatedTestData={this.updateTestData}/>
和父组件,您可以定义方法updateTestData,该方法将更改selectedTestdata的值。
在您的Child组件中,您可以调用此prop方法
testDataReloader = (e) => {
this.props.updateTestData(e.target.value);
console.log(e.target.value);
}