React redux not updating component when adding to array - reactjs

So no matter what I do I can't get the component to refresh when I add a item to an array in the redux store.
What I use in my reducer to add to the redux state:
case ADD_NOTE_META:
return [
...state,
action.note,
];
The connector:
import { connect } from 'react-redux';
import NoteSection from './NoteSection.component';
const mapStateToProps = state => ({
notes: state.NotesMeta,
});
const mapDispatchToProps = () => ({});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(NoteSection);
The component:
import React from 'react';
import PropTypes from 'prop-types';
import NoteSelectorContainer from './noteselector/NoteSelector.connector';
import DeleteConfirmationMessage from './deletenoteconfirmationmessage/DeleteConfirmationMessage.connector';
function NoteSection(props) {
const { notes } = props;
return (
<div id="divSelectNoteContainer">
{notes.map(item => (
<NoteSelectorContainer
note={item}
key={item.id}
/>
))}
<DeleteConfirmationMessage />
</div>
);
}
NoteSection.defaultProps = {
notes: [],
};
NoteSection.propTypes = {
notes: PropTypes.array,
};
export default NoteSection;
The state in redux is structured like:
{
NotesMeta: [
{
id: '5b6cd6c49a46d',
title: 'folder note',
tags: [
'test'
],
parentid: '5b6cd6c49a48d'
},
{
id: '5b6cd6c496ad2',
title: 'test note',
tags: [],
parentid: null
},
]
}
Output of console.log(notes) before add new note is run:
0: {id: "5b6cd6c49a46d", title: "folder note", tags: Array(1), parentid: "5b6cd6c49a48d"}
1: {id: "5b6cd6c496ad2", title: "test note", tags: Array(0), parentid: null}
After:
0: {id: "5b6cd6c49a46d", title: "folder note", tags: Array(1), parentid: "5b6cd6c49a48d"}
1: {id: "5b6cd6c496ad2", title: "test note", tags: Array(0), parentid: null}
2: {id: "5bb48aaae94c1", title: "New Note Title", tags: Array(0)}
I can see that the new note is added in both the redux store and the Notesection props however a new NoteSelectorContainer is never created.

Related

Storybook component not show

I setup Storybook to my project and add stories to my components. In simple components like button or Input stories appear in storybook. When i am creating stories on more advance component i cant see this component in stories. In stories i dont have any errors and i pass all args to component in story. My component looks like this:
return (
<Box>
<Paper>
{projects.map((project) => {
return project.timetracking.map((value) => {
switch (project.strategy) {
case StrategyEnum.HoursMonthly:
return (
<HoursMonthly comment={value.comment} date={value.date} hours={value.hours} />
);
case StrategyEnum.HoursDaily:
return <HoursDaily comment={value.comment} date={value.date} hours={value.hours} />;
case StrategyEnum.HoursPerTask:
return (
<HoursPerTask
comment={value.comment}
date={value.date}
hours={value.hours}
taskUrl={value.taskUrl}
/>
);
default:
return <Text>No strategy match</Text>;
}
});
})}
</Paper>
</Box>
);
};
export default TimetrackingRecords;
I write a story to this component and my story look like this:
title: 'timetracking/Records',
component: TimetrackingRecords,
} as Meta;
const Template: Story<Organization> = (args) => <TimetrackingRecords {...args} />;
export const Monthly = Template.bind({});
Monthly.args = {
id: '12jk4l12kj412rjl12jrkeqwpk',
name: 'Organizacja 1',
description: 'Nice oragnization 3, very nice',
projects: [
{
id: 'qwklkrqwlqkrlqkrw',
name: 'Project 1',
users: [
{ id: 'fdfasfasfs', email: 'test2#test.com', firstName: 'Jan', lastName: 'Kowalski' },
],
strategy: StrategyEnum.HoursMonthly,
timetracking: [
{
id: '5545dasdas54564',
hours: 3,
date: '12/12/2022',
comment: 'simple comment',
taskUrl: 'https://bebit.atlassian.net/browse/TIM-11',
},
],
},
],
users: [{ id: 'qwrlqwjrkwqjrlvn', email: 'test#test.com', firstName: 'John', lastName: 'Doe' }],
};
What i am doing wrong? Story not showing any errors. Maybe i have something wrong with configuration or Component.

How to get subcollection from firestore using react-redux-firebase

I am not able to get the sub-collection from my Firestore data.
I followed the documentation here. And also looked at many other similar question on this.
I can't seem to get the array of data that i want to get.
My code:
import "../../styles/projects/ProjectDashboard.css";
import ProjectList from "./ProjectList";
import { connect } from "react-redux";
import { firestoreConnect } from "react-redux-firebase";
import { compose } from "redux";
import { Redirect } from "react-router-dom";
export class ProjectDashboard extends Component {
render() {
const { projects, auth } = this.props;
if (!auth.uid) return <Redirect to="/sigin" />;
return (
<div className="container">
<h2>Projects</h2>
<ProjectList projects={projects} />
</div>
);
}
}
const mapStateToProps = state => {
console.log(state);
return {
projects: state.firestore.ordered.projects,
auth: state.firebase.auth
};
};
export default compose(
connect(mapStateToProps),
firestoreConnect(props => {
return [
{
collection: "users",
doc: props.auth.uid,
subcollection: [{ collection: "projects" }]
}
];
})
)(ProjectDashboard);
this is what i am getting now from my console :
firestore:
|-composite: undefined
|-data: {users: {…}}
|-errors: {byQuery: {…}, allIds: Array(0)}
|-listeners: {byId: {…}, allIds: Array(1)}
|-ordered:
|--users: Array(1)
|---0: {id: "o06VEyRbGDcURTmKal3gDEDZQO73", firstName: "testing", lastName: "you", userId: "o06VEyRbGDcURTmKal3gDEDZQO73"}
|---length: 1
|---__proto__: Array(0)
|--__proto__: Object
|-queries: {}
|-status: {requesting: {…}, requested: {…}, timestamps: {…}}
|-__proto__: Object
I was thinking that my code will change this part:
|-ordered:
|--users: Array(1)
|---0: {id: "o06VEyRbGDcURTmKal3gDEDZQO73", firstName: "testing", lastName: "you", userId: "o06VEyRbGDcURTmKal3gDEDZQO73"}
to something like this:
|-ordered:
|--projects: Array(3)
|---0: {id: "o06VEyRbGDcURTmKal3gDEDZQO73", firstName: "testing", lastName: "you", userId: "o06VEyRbGDcURTmKal3gDEDZQO73"}
|---1: {id: "o06VEyRbGDcURTmKal3gDEDZQO73", firstName: "testing", lastName: "you", userId: "o06VEyRbGDcURTmKal3gDEDZQO73"}
|---2: {id: "o06VEyRbGDcURTmKal3gDEDZQO73", firstName: "testing", lastName: "you", userId: "o06VEyRbGDcURTmKal3gDEDZQO73"}
so i can get the array through the key. But now i am at a lost on how to change it into my sub-collection key.
I realised that it should be "subcollections" and not "subcollection"

How to mark options as selected

How can i set selected atribute to options inside of <SelectArrayInput> component? I have not realized how to set selected atribute yet.
I have already tried to put there a attribute selected, but it doesnt seem to work.
const tec = [
{ name: "Apple", id: 1, selected: true},
{ name: "Facebook", id: 2 },
{ name: "Netflix", id: 3 },
{ name: "Tesla", id: 4 },
];
const ReferrenceSelectBox = ({ source, record = {} }) => <SelectArrayInput choices={ tec } />;
ReferrenceSelectBox.propTypes = {
label: PropTypes.string,
record: PropTypes.object,
source: PropTypes.string.isRequired,
};
export default ReferrenceSelectBox;
I expect the output of <SelectArrayInput> with already selected options.
I am not able to get a code sandbox working with react-admin, but from the documentation it looks like it is using the Select from Material-ui as the base.
In Material-UI you can pass the values to be selected as a prop: value which takes an array of the ids that you want.
So, in your case, instead of having selected attribute, you can create another array which captures the selectedIds and pass it as value prop and it should work.
const tec = [
{ name: "Apple", id: 1},
{ name: "Facebook", id: 2 },
{ name: "Netflix", id: 3 },
{ name: "Tesla", id: 4 },
];
const selectedTec = [1];
const ReferrenceSelectBox = ({ source, record = {} }) => <SelectArrayInput value={ selectedTec } choices={ tec } />;
ReferrenceSelectBox.propTypes = {
label: PropTypes.string,
record: PropTypes.object,
source: PropTypes.string.isRequired,
};
export default ReferrenceSelectBox;

How do I dynamically determine the propTypes of a react component?

I have a react component as follows:
import {
dataType,
} from './types.js';
class TableUp extends React.Component {
static propTypes = {
palette: t.object,
title: t.string,
data: dataType.isRequired,
selection: t.object,
querySearch: t.object,
pagination: t.object,
onMount: t.func,
};
And in the types.js
import t from 'prop-types';
export const dataValueType = t.shape({
id: t.oneOfType([
t.string,
t.number,
]).isRequired,
name: t.string,
status: t.string,
});
export const dataValuesType = t.arrayOf(dataValueType);
export const dataColumnType = t.shape({
key: t.string.isRequired,
label: t.string.isRequired,
numeric: t.bool,
});
export const dataColumnsType = t.arrayOf(dataColumnType);
export const dataType = t.shape({
values: dataValuesType,
columns: dataColumnsType,
});
When I instantiate the <TableUp> component, I need to pass data that may vary from case to case.
So the following will FAIL to work
const data = {
values: [
{description: "10 percent", allocated: 10.00},
{description: "50 percent", allocated: 50.00},
{description: "40 percent", allocated: 40.00},
],
columns: [
{key: 'attributes.description', label: 'Milestone'},
{key: 'attributes.allocated', label: 'Percent', numeric: true},
]
};
return (
<TableUp inputProps={{name:"gr_table"}} data={data} />
);
I was wondering if there's a way I can dynamically determine the dataType when I instantiate the TableUp component.

Redux not passing state to props

I connected a component to the store in a way that it's able to dispatch actions and receive state. The dispatch works and I can see the state change in the Redux dev tool. However, I'm unable to pass the state back to the component. What am I missing here?
Component
The toggle() and addTask() are successfully dispatched. However, the newTask doesn't receive the state.
class AddTask extends React.Component {
state = {
value: '',
};
setValue = value => this.setState({ value });
handleInput = () => !this.props.newTask ? 'hidden' : '';
handleToggle = () => this.props.toggle();
handleSubmit = (e) => {
e.preventDefault();
const title = this.state.value;
this.props.addTask(title);
this.props.toggle();
};
render() {
return (
<div className="add-task">
<div className="btn-add-task">
<Button
type="LINK"
label="Add a Task"
onClick={this.handleToggle}
/>
</div>
<form
className={`task-input ${this.handleInput()}`}
onSubmit={this.handleSubmit}
>
<InputField
placeholder="Task title"
value={value => this.setValue(value)}
/>
</form>
</div>
);
}
};
export default AddTask;
Container
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import AddTask from './TaskList/AddTask/AddTask';
import * as actionCreators from '../actions/taskActions';
const mapStateToProps = state => ({
newTask: state.newTask,
});
const mapDispatchToProps = dispatch => (
bindActionCreators(actionCreators, dispatch)
);
export default connect(
mapStateToProps,
mapDispatchToProps,
)(AddTask);
Reducer
import {
TOGGLE_TASK,
} from '../constants/actions';
const uiReducer = (state = {
newTask: false,
}, action) => {
switch (action.type) {
case TOGGLE_TASK:
return {
...state,
newTask: !state.newTask,
};
default:
return state;
}
};
export default uiReducer;
Store
const initialState = {
tasks: [
{
title: 'Title A', description: 'Description A', effort: '12 hrs', editing: 'false',
},
{
title: 'Title B', description: 'Description B', effort: '24 hrs', editing: 'false',
},
{
title: 'Title C', description: 'Description C', effort: '', editing: 'false',
},
],
ui: {
newTask: false,
},
};
Print
tasks: Array(4)
0: {title: "Title A", description: "Description A", effort: "12 hrs", editing: "false"}
1: {title: "Title B", description: "Description B", effort: "24 hrs", editing: "false"}
2: {title: "Title C", description: "Description C", effort: "", editing: "false"}
3: {id: "", title: "asdfasd", description: undefined}
length: 4
__proto__: Array(0)
ui:
newTask: false
Thanks!

Resources