问题
I am using react-redux-firebase. This is how my firebase data looks like once user submit the form:
It pushes information to "contacts" and images to "uploadedFiles"(also used for file Storage path). I really want to have it as one item. Something like:
contacts = {
kydfsdcfasdfsadf :{
email: "user@gmail.com",
firstName: Tom,
lastName : "Smith",
uploasedFiles:{
downloadURL:"dsfsdfsdsdvsdfgdsfgds",
fullPath:"dfsdfsdf",
mame:"q34deser4wefwsdf"
}
}
}
I feel like I should use Populate, but I can not find how to populate one item with another. Will really appreciate any suggestion and useful links.
Here is the code: AddContactForm.js
import { Field, reduxForm } from 'redux-form';
import { browserHistory } from 'react-router';
import Uploader from '../components/Uploader';
const capitalize = value => value.charAt(0).toUpperCase() + value.substring(1);
const lower = value => value && value.toLowerCase();
const AddContactForm = props => {
const { handleSubmit } = props;
return (
<div>
<h1> Add New Contact</h1>
<hr />
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" normalize={capitalize} />
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" component="input" type="text" normalize={capitalize} />
</div>
<div>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email" normalize={lower} />
</div>
<Uploader />
<button type="submit">Submit</button>
<button onClick={() => { browserHistory.push('/'); }} >Cancel</button>
</form>
</div>
);
};
AddContactForm = reduxForm({
// a unique name for the form
form: 'contact'
})(AddContactForm)
export default AddContactForm;
Uploader.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { compose, bindActionCreators } from 'redux';
import { firebaseConnect, dataToJS, getFirebase } from 'react-redux-firebase';
import { map } from 'lodash';
import Dropzone from 'react-dropzone';
// Path within Database for metadata (also used for file Storage path)
const filesPath = 'uploadedFiles';
class Uploader extends Component {
onFilesDrop(files) {
const firebase = getFirebase();
// Uploads files and push's objects containing metadata to database at dbPath
// uploadFiles(storagePath, files, dbPath)
firebase.uploadFiles(filesPath, files, filesPath);
}
onFileDelete(file, key) {
const firebase = getFirebase();
// Deletes file and removes metadata from database
// deleteFile(storagePath, dbPath)
firebase.deleteFile(file.fullPath, `${filesPath}/${key}`);
}
render() {
const { uploadedFiles } = this.props
return (
<div>
<Dropzone onDrop={this.onFilesDrop}>
<div>
Drag and drop files here
or click to select
</div>
</Dropzone>
{
uploadedFiles &&
<div>
<h3>
Uploaded file(s):
</h3>
{
map(uploadedFiles, (file, key) => (
<div key={file.name + key}>
<span>{file.name}</span>
<button onClick={() => this.onFileDelete(file, key)}>
Delete File
</button>
</div>
))
}
</div>
}
</div>
);
}
}
Uploader.propTypes = {
firebase: PropTypes.object.isRequired,
uploadedFiles: PropTypes.object
};
export default compose(
firebaseConnect([
filesPath
]),
connect(
({ firebase }) => ({
uploadedFiles: dataToJS(firebase, filesPath)
})
)
)(Uploader);
AddContact.js
import React from 'react';
import { getFirebase, firebaseConnect, dataToJS } from 'react-redux-firebase';
import { browserHistory } from 'react-router';
import { connect } from 'react-redux';
import { compose } from 'redux';
import AddContactForm from './AddContactForm';
class AddContact extends React.Component {
submit(values) {
const firebase = getFirebase();
firebase
.push('contacts', values)
// .push('contacts', Object.assign({}, values, { img: 'here I need to pass uploadedFiles' }))
.then(() => {
browserHistory.push('/');
});
}
render() {
const { uploadedFiles } = this.props;
const uploadArr = uploadedFiles&&Object.values(uploadedFiles);
const fileToAdd = uploadedFiles&&uploadArr[uploadArr.length-1].downloadURL
console.log('uploadedFiles!', uploadedFiles&&fileToAdd);
return (
<div className="container">
<AddContactForm onSubmit={this.submit} />
</div>
);
}
}
export default compose(
firebaseConnect([
{ path: 'contacts', queryParams: ['orderByValue'] },
{ path: 'uploadedFiles', queryParams: ['orderByValue'] }
]),
connect(
(state) => ({
uploadedFiles: dataToJS(state.firebase, 'uploadedFiles')
}),
)
)(AddContact)
回答1:
I would suggest to follow the React Redux "Way" of dealing with Firebase and that to create an Action that deals with Firebase which i am not sure if i am missing it in your code or not. However, when you upload the files in storage you need to set the URI into your Firebase database reference. you should get a URI as a result when you upload a file into the Firebase Storage.
export function createAccount(data, picture) {
const { fname, lname, email, password, image } = data;
storage.child(`/${picture.name}/${new Date().getTime()}`).put(image[0]).then((snapshot) => {
database.ref('contacts').child(youruserID).set({
email: "user@gmail.com",
firstName: Tom,
lastName : "Smith",
uploadedfile: snapshot.metadata.downloadURLs[0]
});
});
}
来源:https://stackoverflow.com/questions/47205654/react-redux-firebase-populate-item-with-another-item